|
Step 3: Adding Comms |
Top Previous Next |
This sample project is published on our website under the name "test_stg_lib".
OK, now comms. We use terminal software, for example, our own I/O Ninja software (ninja.tibbo.com) to send commands and receive replies. The "IP" setting defines the IP address of the device, while the "PN" setting specifies the port number on the device side. Setting initialization will cause these settings to have default values of 192.168.1.93 and 1000, as specified in the settings.txt descriptor file.
Writing and Reading Settings already explained the difference between the usage of stg_get()/stg_set() and stg_sg(). Here is a practical illustration: comms_init() below uses a "simplified" stg_get(). With this, there is no need to check the execution result each time we need to read a setting -- should there be any problem, callback_stg_error() will be called and we respond to the error there.
Comms_proc_cmd(), on the contrary, needs to respond to each command with a meaningful status code. This is why it relies on stg_sg(), which returns the status code directly.
There are two commands: "S" (set setting) and "G" (get setting). Both commands should end with the CR (shown as <CR> below).
Set command format is Ssetting_name,index,setting_value. The command returns the execution result, which is expressed by a single character (see below).
Get command format is Gsetting_name,index. The command returns the execution result. If execution was successful, setting value is also returned.
Execution result codes are: A for OK, C for when the setting name is unknown or the index is invalid, F when there was some sort of failure, I when the setting value is invalid, and U for "weird internal errors".
Here is a sample printout from I/O Ninja, we write and read one of the "PTN" setting's members. We set this member to "R-G-B-" and then read this value back:
Established TCP connection with 192.168.1.40:1000 from 3790 SPTN,2,R-G-B-<CR> A<CR> GPTN,2<CR> AR-G-B-<CR>
|
And here is the full code...
global.tbh: |
'DEFINES-------------------------------------------------------------
'INCLUDES------------------------------------------------------------ include "settings\trunk\settings.tbh" includepp "settings.txt" 'this will allow you to put #defines directly into settings.txt include "sock\trunk\sock.tbh"
'DECLARATIONS-------------------------------------------------------- declare sub comms_init() declare sub comms_proc_cmd()
|
main.tbs: |
include "global.tbh"
'==================================================================== sub on_sys_init() dim x as en_stg_status_codes dim stg_name as string(STG_MAX_SETTING_NAME_LEN)
if stg_start()<>EN_STG_STATUS_OK then sys.halt
x=stg_check_all(stg_name) select case x case EN_STG_STATUS_OK: '--- all good ---
case EN_STG_STATUS_INVALID, EN_STG_STATUS_FAILURE: if stg_restore_multiple(EN_STG_INIT_MODE_NORMAL)<>EN_STG_STATUS_OK then sys.halt
case else: 'some other trouble sys.halt end select
comms_init() end sub
'-------------------------------------------------------------------- sub on_button_released() if button.time>4 then if stg_restore_multiple(EN_STG_INIT_MODE_NORMAL)<>EN_STG_STATUS_OK then sys.halt sys.reboot end if end sub
'-------------------------------------------------------------------- sub on_sock_data_arrival() comms_proc_cmd() end sub
|
device.tbs: |
include "global.tbh"
'-------------------------------------------------------------------- dim comms_sock as byte
'==================================================================== sub callback_stg_error(byref stg_name_or_num as string,index as byte,status as en_stg_status_codes) end sub
'-------------------------------------------------------------------- sub callback_stg_pre_get(byref stg_name_or_num as string,index as byte,byref stg_value as string) end sub
'-------------------------------------------------------------------- sub callback_stg_post_set(byref stg_name_or_num as string, index as byte,byref stg_value as string) end sub
'-------------------------------------------------------------------- sub comms_init() net.ip=stg_get("IP",0)
comms_sock=sock_get("COMM") if comms_sock=255 then sys.halt
sock.num=comms_sock sock.rxbuffrq(1) sock.txbuffrq(1) sys.buffalloc
sock.protocol=PL_SOCK_PROTOCOL_TCP sock.localportlist=stg_get("PN",0) sock.inconmode=PL_SOCK_INCONMODE_ANY_IP_ANY_PORT sock.reconmode=PL_SOCK_RECONMODE_3 end sub
'-------------------------------------------------------------------- sub comms_proc_cmd() dim pos as byte dim s as string dim stg_name as string(STG_MAX_SETTING_NAME_LEN) dim stg_value as string(STG_MAX_SETTING_VALUE_LEN) dim index as byte dim result as en_stg_status_codes
if sock.num=comms_sock then pos=instr(1,sock.peekdata(255),chr(13),1) 'is there CR in the buffer if pos=0 then 'this is to prevent buffer overflow with garbage if sock.rxlen=sock.txbuffsize then s=sock.getdata(255) end if else 'yes, there is CR -- we have a complete command s=sock.getdata(pos) s=left(s,len(s)-1)
'eliminate LF if present if asc(left(s,1))=10 then s=right(s,len(s)-1) end if
'process this command select case asc(left(s,1)) case `S`: 'set setting, is index specified? s=right(s,len(s)-1) pos=instr(1,s,",",1) if pos=0 then stg_name=s index=0 else stg_name=left(s,pos-1) index=val(mid(s,pos+1,255)) end if
'is value specified? s=mid(s,pos+1,255) pos=instr(1,s,",",1) if pos=0 then stg_value=0 else stg_value=mid(s,pos+1,255) end if
result=stg_sg(stg_name,index,stg_value,EN_STG_SET) s=""
case `G`: 'get setting, is index specified? s=right(s,len(s)-1) pos=instr(1,s,",",1) if pos=0 then stg_name=s index=0 else stg_name=left(s,pos-1) index=val(mid(s,pos+1,255)) end if
result=stg_sg(stg_name,index,s,EN_STG_GET)
case else: result=EN_STG_STATUS_UNKNOWN end select
'common portion -- generate reply select case result case EN_STG_STATUS_OK: s="A"+s
case EN_STG_STATUS_UNKNOWN, EN_STG_STATUS_INVALID_INDEX: s="C" 'invalid setting name or index
case EN_STG_STATUS_FAILURE: s="F" 'failure (hardware, etc.)
case EN_STG_STATUS_INVALID: s="I" 'invalid value
case else: s="U" 'some internal error end select
sock.setdata(s) sock.send end if end if end sub
|
settings.txt: |
>>DN E S 1 0 10 I ^ Device Name >>IP E D 1 4 4 A 192.168.1.93 IP address <-- set the one you want as the default value >>PN E W 1 0 65535 A 1000 Port number >>PTN E S 3 0 16 A G-~/R-~/B-~ LED patterns >>CPTN R B 1 0 2 A 0 Current pattern to play
#define STG_DEBUG_PRINT 1 #define STG_MAX_SETTING_NAME_LEN 4 #define STG_MAX_NUM_SETTINGS 5 #define STG_RAM_ARRAY_SIZE 2
|