Skip to content

Conversation

@ceremcem
Copy link
Contributor

Functions return the header.SID value in order to correctly match the sent command with the reply.

Example code:

export class OmronFinsDriver extends DriverAbstract
    (@opts={}) ->
        super!
        @log = new Logger \OmronFinsDriver
        @target = {port: 9600, host: '192.168.250.1'} <<< @opts
        @timeout = 2000ms  # 100ms

        @log.log bg-yellow "Using #{@target.host}:#{@target.port}"
        @client = fins.FinsClient @target.port, @target.host

        @q = {} # exec queue. Key field is the sequence number (FinsClient.SID).

        @client.on \reply, (msg) ~>
            if msg.sid of @q
                # got an expected reply
                @q[msg.sid].go err=null, res=msg 
                delete @q[msg.sid]
            else 
                @log.error "Unexpected response: (none in #{Object.keys @q}):", msg

        @client.on \error, (err) ~> 
            @log.error "FINS Client error:", err 

        @client.on \timeout, (err) ~> 
            @log.error "FINS timeout:", err

        # PLC connection status 
        @connected = no 
        @on \connected, ~> 
            @log.info "Connected to PLC"
        @on \disconnected, ~> 
            @log.info "Disconnected from PLC"

        @check-heartbeating!


    check-heartbeating: ->>
        @log.log "Starting the heartbeat check with the PLC"
        while true
            try await @exec \read, "C0:0", 1
            await sleep 10_000ms
   
    exec: (command, ...args) ->> 
        # This is the key function that transforms the discrete .read/.write functions 
        # into async functions        
        SID = @client[command] ...args
        @q[SID] = new Signal!
        return new Promise (resolve, reject) ~>
            @q[SID].wait @timeout, (err, res) ~> 
                if err 
                    reject(err)
                    @trigger \disconnected if @connected
                    @connected = no 
                    sleep 0 ~> 
                        delete @q[SID] if SID of @q
                else 
                    resolve(res)
                    @trigger \connected unless @connected
                    @connected = yes

This is the current code I'm using for as a wrapper class. I use this driver as follows:

driver = new OmronFinsDriver()
try 
    value = await driver.exec 'read', 'DM0:0', 1
catch 
    console.error "Something went wrong while reading"

# or 

try
    await driver.exec 'write', 'DM0:0', 1
catch
  console.error "Something went wrong while writing"

In order to make this kind of usage possible, I need to match the sent command with the reply. Here the SID value plays a key role. Thereby, functions must return the SID value they are using in order to let us match the sent command with its reply.

Functions return the `header.SID` value in order to correctly match the sent command with the reply.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant