示例#1
0
// Inline function and macros
inline MyMessage& build (MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) {
	msg.sender = sender;
	msg.destination = destination;
	msg.sensor = sensor;
	msg.type = type;
	mSetCommand(msg,command);
	mSetRequestAck(msg,enableAck);
	mSetAck(msg,false);
	return msg;
}
void incomingMQTT(char* topic, byte* payload,
                        unsigned int length)
{
	debug(PSTR("Message arrived on topic: %s\n"), topic);
	char *str, *p;
	uint8_t i = 0;
	for (str = strtok_r(topic, "/", &p); str && i <= 5;
			str = strtok_r(NULL, "/", &p)) {
		switch (i) {
			case 0: {
				// Topic prefix
				if (strcmp_P(str, MY_MQTT_TOPIC_PREFIX) != 0) {
					// Message not for us or malformed!
					return;
				}
				break;
			}
			case 1: {
				// Node id
				_mqttMsg.destination = atoi(str);
				break;
			}
			case 2: {
				// Sensor id
				_mqttMsg.sensor = atoi(str);
				break;
			}
			case 3: {
				// Command type
				mSetCommand(_mqttMsg, atoi(str));
				break;
			}
			case 4: {
				// Ack flag
				mSetRequestAck(_mqttMsg, atoi(str)?1:0);
				break;
			}
			case 5: {
				// Sub type
				_mqttMsg.type = atoi(str);
				// Add payload
				char* ca;
				ca = (char *) payload;
				ca += length;
				*ca = '\0';
				_mqttMsg.set((const char*) payload);
				_available = true;
			}
		}
		i++;
	}
}
示例#3
0
bool MySensor::send(MyMessage &message, bool enableAck) {
	message.sender = nc.nodeId;
	mSetCommand(message,C_SET);
    mSetRequestAck(message,enableAck);
	return sendRoute(message);
}
示例#4
0
bool MyParserSerial::parse(MyMessage &message, char *inputString) {
	char *str, *p, *value=NULL;
	uint8_t bvalue[MAX_PAYLOAD];
	uint8_t blen = 0;
	int i = 0;
	uint8_t command = 0;
	uint8_t ack = 0;

	// Extract command data coming on serial line
	for (str = strtok_r(inputString, ";", &p); // split using semicolon
		str && i < 6; // loop while str is not null an max 5 times
		str = strtok_r(NULL, ";", &p) // get subsequent tokens
			) {
		switch (i) {
			case 0: // Radioid (destination)
				message.destination = atoi(str);
				break;
			case 1: // Childid
				message.sensor = atoi(str);
				break;
			case 2: // Message type
				command = atoi(str);
				mSetCommand(message, command);
				break;
			case 3: // Should we request ack from destination?
				ack = atoi(str);
				break;
			case 4: // Data type
				message.type = atoi(str);
				break;
			case 5: // Variable value
				if (command == C_STREAM) {
					blen = 0;
					uint8_t val;
					while (*str) {
						val = h2i(*str++) << 4;
						val += h2i(*str++);
						bvalue[blen] = val;
						blen++;
					}
				} else {
					value = str;
					// Remove ending carriage return character (if it exists)
					uint8_t lastCharacter = strlen(value)-1;
					if (value[lastCharacter] == '\r')
						value[lastCharacter] = 0;
				}
				break;
		}
		i++;
	}
	// Check for invalid input
	if (i < 5)
		return false;

	message.sender = GATEWAY_ADDRESS;
	message.last = GATEWAY_ADDRESS;
    mSetRequestAck(message, ack?1:0);
    mSetAck(message, false);
	if (command == C_STREAM)
		message.set(bvalue, blen);
	else
		message.set(value);
	return true;
}
示例#5
0
void MyGateway::parseAndSend(char *commandBuffer) {
  boolean ok = false;
  char *str, *p, *value=NULL;
  uint8_t bvalue[MAX_PAYLOAD];
  uint8_t blen = 0;
  int i = 0;
  uint16_t destination = 0;
  uint8_t sensor = 0;
  uint8_t command = 0;
  uint8_t type = 0;
  uint8_t ack = 0;

  // Extract command data coming on serial line
  for (str = strtok_r(commandBuffer, ";", &p);       // split using semicolon
  		str && i < 6;         // loop while str is not null an max 5 times
  		str = strtok_r(NULL, ";", &p)               // get subsequent tokens
				) {
	switch (i) {
	  case 0: // Radioid (destination)
	 	destination = atoi(str);
		break;
	  case 1: // Childid
		sensor = atoi(str);
		break;
	  case 2: // Message type
		command = atoi(str);
		break;
	  case 3: // Should we request ack from destination?
		ack = atoi(str);
		break;
	  case 4: // Data type
		type = atoi(str);
		break;
	  case 5: // Variable value
		if (command == C_STREAM) {
			blen = 0;
			uint8_t val;
			while (*str) {
				val = h2i(*str++) << 4;
				val += h2i(*str++);
				bvalue[blen] = val;
				blen++;
			}
		} else {
			value = str;
		}
		break;
	  }
	  i++;
  }

  if (destination==GATEWAY_ADDRESS && command==C_INTERNAL) {
    // Handle messages directed to gateway
    if (type == I_VERSION) {
      // Request for version
      serial(PSTR("0;0;%d;0;%d;%s\n"),C_INTERNAL, I_VERSION, LIBRARY_VERSION);
    } else if (type == I_INCLUSION_MODE) {
      // Request to change inclusion mode
      setInclusionMode(atoi(value) == 1);
    }
  } else {
    txBlink(1);
    msg.sender = GATEWAY_ADDRESS;
	msg.destination = destination;
	msg.sensor = sensor;
	msg.type = type;
	mSetCommand(msg,command);
	mSetRequestAck(msg,ack?1:0);
	mSetAck(msg,false);
	msg.set(value);
	if (command == C_STREAM)
		msg.set(bvalue, blen);
	else
		msg.set(value);
    ok = sendRoute(msg);
    if (!ok) {
      errBlink(1);
    }
  }
}
bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsigned int length)
{
	char *str, *p;
	uint8_t i = 0;
	uint8_t bvalue[MAX_PAYLOAD];
	uint8_t blen = 0;
	uint8_t command = 0;
	if (topic != strstr(topic, MY_MQTT_SUBSCRIBE_TOPIC_PREFIX)) {
		// Prefix doesn't match incoming topic
		return false;
	}
	for (str = strtok_r(topic + strlen(MY_MQTT_SUBSCRIBE_TOPIC_PREFIX) + 1, "/", &p); str && i <= 5;
	        str = strtok_r(NULL, "/", &p)) {
		switch (i) {
		case 0: {
			// Node id
			message.destination = atoi(str);
			break;
		}
		case 1: {
			// Sensor id
			message.sensor = atoi(str);
			break;
		}
		case 2: {
			// Command type
			command = atoi(str);
			mSetCommand(message, command);
			break;
		}
		case 3: {
			// Ack flag
			mSetRequestAck(message, atoi(str)?1:0);
			break;
		}
		case 4: {
			// Sub type
			message.type = atoi(str);
			break;
		}
		}
		i++;
	}

	if (i != 5) {
		return false;
	}

	message.sender = GATEWAY_ADDRESS;
	message.last = GATEWAY_ADDRESS;
	mSetAck(message, false);

	// Add payload
	if (command == C_STREAM) {
		blen = 0;
		uint8_t val;
		while (*payload) {
			val = protocolH2i(*payload++) << 4;
			val += protocolH2i(*payload++);
			bvalue[blen] = val;
			blen++;
		}
		message.set(bvalue, blen);
	} else {
		char* ca;
		ca = (char *) payload;
		ca += length;
		*ca = '\0';
		message.set((const char*) payload);
	}

	return true;
}
示例#7
0
// main start
int main(void) {	
	
	asm volatile ("clr __zero_reg__");
	// reset MCU status register	
	MCUSR = 0;
	
	// enable watchdog to avoid deadlock
	watchdogConfig(WATCHDOG_8S);

	// initialize SPI
	SPIinit();
		
	// initialize RF module	
	RFinit();

	// Read node config from EEPROM, i.e. nodeId, parent nodeId, distance
	eeprom_read_block((void*)&nc, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(struct NodeConfig));
	// Read firmware config from EEPROM, i.e. type, version, CRC, blocks
	eeprom_read_block((void*)&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig));
	
	// find nearest node during reboot: invalidate parent node settings, since we have to re-discover them for every single reboot
	configuredParentID = nc.parentNodeId;
	// nc.parentNodeId = 0xFF;
	nc.distance = 0xFF;
	
	// prepare for I_FIND_PARENTS
	outMsg.sender = nc.nodeId;
	outMsg.last = nc.nodeId;
	outMsg.sensor = 0xFF;
	outMsg.destination = BROADCAST_ADDRESS;
	
	// set header
	mSetVersion(outMsg, PROTOCOL_VERSION);
	mSetLength(outMsg, 0);
	mSetCommand(outMsg, C_INTERNAL);
	mSetAck(outMsg,false);
	mSetPayloadType(outMsg, P_STRING);
	
	// set reading & writing pipe address
	setAddress(nc.nodeId);

	// network up? get neighbors, else startup
	if (!sendAndWait(I_FIND_PARENT, I_FIND_PARENT_RESPONSE)) {
		startup();
	}
	
	// all messages to gateway
	outMsg.destination = GATEWAY_ADDRESS;
	
	// if no node id assigned, request new id
	if (nc.nodeId == AUTO) {
		// listen to broadcast
		openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(BROADCAST_ADDRESS));
		if (sendAndWait(I_ID_REQUEST, I_ID_RESPONSE)) {
			// save id to eeprom
			eeprom_update_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, atoi(inMsg.data));
		}
		// we could go on and set everything right here, but rebooting will take care of that - and saves some bytes :)
		reboot();				
	}
	
	// wuff
	watchdogReset();
	// prepare for FW config request
	RequestFirmwareConfig *reqFWConfig = (RequestFirmwareConfig *)outMsg.data;	
	mSetLength(outMsg, sizeof(RequestFirmwareConfig));
	mSetCommand(outMsg, C_STREAM);
	mSetPayloadType(outMsg,P_CUSTOM);
	// copy node settings to reqFWConfig
	memcpy(reqFWConfig,&fc,sizeof(NodeFirmwareConfig));
	// add bootloader information
	reqFWConfig->BLVersion = MYSBOOTLOADER_VERSION;
	
	// send node config and request FW config from controller
	if (!sendAndWait(ST_FIRMWARE_CONFIG_REQUEST, ST_FIRMWARE_CONFIG_RESPONSE)) {
		startup();
	}
	
	NodeFirmwareConfig *firmwareConfigResponse = (NodeFirmwareConfig *)inMsg.data;
	
	// bootloader commands
	if (firmwareConfigResponse->blocks == 0) {
		// verify flag
		if (firmwareConfigResponse->crc == 0xDA7A){
			// cmd 0x01 clear eeprom
			if(firmwareConfigResponse->bl_command == 0x01) {
				for(uint16_t i = 0; i < EEPROM_SIZE; i++) eeprom_update_byte((uint8_t *)i,0xFF);
			} else 
			// cmd 0x02 set id
			if(firmwareConfigResponse->bl_command == 0x02) {
				eeprom_update_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, (uint8_t)firmwareConfigResponse->bl_data);
			}
		}
		// final step
		reboot();
	}
	
	// compare with current node configuration, if equal startup
	if (!memcmp(&fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig))) {
		startup();
	}
	
	// *********** from here on we will fetch new FW
	
	// invalidate current CRC
	fc.crc = 0xFFFF;
	// write fetched type and version in case OTA fails (BL will reboot and re-request FW with stored settings)
	eeprom_update_block(&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS,sizeof(NodeFirmwareConfig));
	
	// copy new FW config
	memcpy(&fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig));
	RequestFWBlock *firmwareRequest = (RequestFWBlock *)outMsg.data;
	mSetLength(outMsg, sizeof(RequestFWBlock));
	
	firmwareRequest->type = fc.type;
	firmwareRequest->version = fc.version;
	
	// request FW from controller, load FW counting backwards
	uint16_t block = fc.blocks;
	do {
		firmwareRequest->block = block - 1;
		
		// request FW block
		if (!sendAndWait(ST_FIRMWARE_REQUEST, ST_FIRMWARE_RESPONSE)) {
			reboot();
		}
		
		ReplyFWBlock *firmwareResponse = (ReplyFWBlock *)inMsg.data;
		
		// did we receive requested block?
		if (!memcmp(firmwareRequest,firmwareResponse,sizeof(RequestFWBlock))) {
			// calculate page offset
			uint8_t offset = ((block - 1) * FIRMWARE_BLOCK_SIZE) % SPM_PAGESIZE;
			// write to buffer
			memcpy(progBuf + offset, firmwareResponse->data, FIRMWARE_BLOCK_SIZE);
			// program if page full
			if (offset == 0) {
				programPage(((block - 1) * FIRMWARE_BLOCK_SIZE), progBuf);
			}
			block--;	
		}	
	} while (block);
	
	// wuff
	watchdogReset();
	
	// all blocks transmitted, calc CRC and write to eeprom if valid	
	if (IsFirmwareValid()) {
		// if FW is valid, write settings to eeprom 
		eeprom_update_block(&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig));
	} 
	// final step
	reboot();
}