Example #1
0
def build (sender, destination, sensor, command, typ, enableAck):
    msg = MyMessage()
    msg.sender = sender
    msg.destination = destination
    msg.sensor = sensor
    msg.type = typ
    mSetCommand(msg,command)
    mSetRequestAck(msg,enableAck)
    mSetAck(msg,False)
    return msg
Example #2
0
    def process(self):
#         hw_watchdogReset()
        
        available,to = self.radio.available()
        if not available:
            return False
    
        msg = MyMessage()
        self.msg = msg
        data = self.radio.receive()
        msg.raw = data
    
    
        # Add string termination, good if we later would want to print it.
        #msg.data[mGetLength(msg)] = '\0'
        debug("read: %s-%s-%s sensor=%s,command=%s,type=%s,payloadtype=%s,length=%s,sg=%s:%s\n"%(
                    msg.sender, msg.last, msg.destination, msg.sensor, mGetCommand(msg), msg.type, mGetPayloadType(msg), mGetLength(msg), mGetSigned(msg), msg.getString()))
        mSetSigned(msg,0) # Clear the sign-flag now as verification (and debug printing) is completed
    
        if mGetVersion(msg) != PROTOCOL_VERSION:
            debug("version mismatch")
            return False
    
        command = mGetCommand(msg)
        typ = msg.type
        sender = msg.sender
        last = msg.last
        destination = msg.destination
    
        if destination == self.nc.nodeId:
            # This message is addressed to this node
    
            if (self.repeaterMode and last != self.nc.parentNodeId):
                # Message is from one of the child nodes. Add it to routing table.
                hw_writeConfig(EEPROM_ROUTES_ADDRESS+sender, last)
    
            # Check if sender requests an ack back.
            if (mGetRequestAck(msg)):
                # Copy message
                tmpMsg = msg
                mSetRequestAck(tmpMsg,False) # Reply without ack flag (otherwise we would end up in an eternal loop)
                mSetAck(tmpMsg,True)
                tmpMsg.sender = self.nc.nodeId
                tmpMsg.destination = msg.sender
                self.sendRoute(tmpMsg)
    
            if (command == Command.C_INTERNAL):
                if (typ == Internal.I_FIND_PARENT_RESPONSE):
                    if (self.autoFindParent):
                        # We've received a reply to a FIND_PARENT message. Check if the distance is
                        # shorter than we already have.
                        distance = msg.getByte()
                        if (isValidDistance(distance)):
                            # Distance to gateway is one more for us w.r.t. parent
                            distance+=1
                            if (isValidDistance(distance) and (distance < self.nc.distance)):
                                # Found a neighbor closer to GW than previously found
                                self.nc.distance = distance
                                self.nc.parentNodeId = msg.sender
                                hw_writeConfig(EEPROM_PARENT_NODE_ID_ADDRESS, self.nc.parentNodeId)
                                hw_writeConfig(EEPROM_DISTANCE_ADDRESS, self.nc.distance)
                                debug(PSTR("parent=%d, d=%d\n"), self.nc.parentNodeId, self.nc.distance)
                    return False
                elif (sender == GATEWAY_ADDRESS):
    
                    if (typ == Internal.I_REBOOT):
                        # Requires MySensors or other bootloader with watchdogs enabled
                        hw_reboot()
                    elif (typ == Internal.I_ID_RESPONSE):
                        if (self.nc.nodeId == AUTO):
                            self.nc.nodeId = msg.getByte()
                            if (self.nc.nodeId == AUTO):
                                # sensor net gateway will return max id if all sensor id are taken
                                debug(PSTR("full\n"))
                                raise(Exception('full'))
#                                 while (1) # Wait here. Nothing else we can do...
                            self.setupNode()
                            # Write id to EEPROM
                            hw_writeConfig(EEPROM_NODE_ID_ADDRESS, self.nc.nodeId)
                            debug(PSTR("id=%d\n"), self.nc.nodeId)
                    elif (typ == Internal.I_CONFIG):
                        # Pick up configuration from controller (currently only metric/imperial)
                        # and store it in eeprom if changed
                        isMetric = msg.getString()[0] == 'M' 
                        self.cc.isMetric = isMetric
                        hw_writeConfig(EEPROM_CONTROLLER_CONFIG_ADDRESS, isMetric)
                    elif (typ == Internal.I_CHILDREN):
                        if (self.repeaterMode and msg.getString()[0] == 'C'):
                            # Clears child relay data for this node
                            debug(PSTR("clear\n"))
#                             i = 255
                            for i in range(255,0,-1):
                                hw_writeConfig(EEPROM_ROUTES_ADDRESS+i, 0xff)
                            # Clear parent node id & distance to gw
                            hw_writeConfig(EEPROM_PARENT_NODE_ID_ADDRESS, 0xFF)
                            hw_writeConfig(EEPROM_DISTANCE_ADDRESS, 0xFF)
                            # Find parent node
                            self.findParentNode()
                            self.sendRoute(build(msg, self.nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, Command.C_INTERNAL, Internal.I_CHILDREN,False).set(""))
                    elif (typ == Internal.I_TIME):
                        if (self.timeCallback != None):
                            # Deliver time to callback
                            self.timeCallback(msg.getULong())
                    return False
            # Call incoming message callback if available
            if (self.msgCallback != None):
                self.msgCallback(self,msg)
            # Return True if message was addressed for this node...
            return True
        elif (self.repeaterMode and self.nc.nodeId != AUTO):
            # If this node have an id, relay the message
    
            if (command == Command.C_INTERNAL and typ == Internal.I_FIND_PARENT):
                if (sender != self.nc.parentNodeId):
                    if (self.nc.distance == DISTANCE_INVALID):
                        self.findParentNode()
    
                    if (self.nc.distance != DISTANCE_INVALID):
                        # Relaying nodes should always answer ping messages
                        # Wait a random delay of 0-2 seconds to minimize collision
                        # between ping ack messages from other relaying nodes
                        self.wait(hw_millis() & 0x3ff)
                        self.sendWrite(sender, build(self.nc.nodeId, sender, NODE_SENSOR_ID, Command.C_INTERNAL, Internal.I_FIND_PARENT_RESPONSE, False).set_uint(self.nc.distance))
            elif (to == self.nc.nodeId):
                # We should try to relay this message to another node
                self.sendRoute(msg)
        return False