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