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
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