Beispiel #1
0
void sendSketchInfo(const char *name, const char *version, bool enableAck) {
	if (name != NULL) {
		_sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, enableAck).set(name));
	}
    if (version != NULL) {
    	_sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, enableAck).set(version));
    }
}
Beispiel #2
0
// Helper to process nonce request mesages
static bool signerInternalProcessNonceRequest(MyMessage &msg)
{
#if defined(MY_SIGNING_FEATURE)
#if defined(MY_NODE_LOCK_FEATURE)
	nof_nonce_requests++;
	SIGN_DEBUG(PSTR("Nonce requests left until lockdown: %d\n"),
	           MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests);
	if (nof_nonce_requests >= MY_NODE_LOCK_COUNTER_MAX) {
		_nodeLock("TMNR"); //Too many nonces requested
	}
#endif // MY_NODE_LOCK_FEATURE
	if (signerBackendGetNonce(msg)) {
		if (!_sendRoute(build(msg, msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_NONCE_RESPONSE))) {
			SIGN_DEBUG(PSTR("Failed to transmit nonce!\n"));
		} else {
			SIGN_DEBUG(PSTR("Transmitted nonce\n"));
		}
	} else {
		SIGN_DEBUG(PSTR("Failed to generate nonce!\n"));
	}
#else // not MY_SIGNING_FEATURE
	(void)msg;
	SIGN_DEBUG(PSTR("Received nonce request, but signing is not supported (message ignored)\n"));
#endif // MY_SIGNING_FEATURE
	return true; // No need to further process I_NONCE_REQUEST
}
Beispiel #3
0
bool signerSignMsg(MyMessage &msg)
{
	bool ret;
#if defined(MY_SIGNING_FEATURE)
	// If destination is known to require signed messages and we are the sender,
	// sign this message unless it is identified as an exception
	if (DO_SIGN(msg.destination) && msg.sender == getNodeId()) {
		if (skipSign(msg)) {
			ret = true;
		} else {
			// Send nonce-request
			_signingNonceStatus=SIGN_WAITING_FOR_NONCE;
			if (!_sendRoute(build(_msgSign, msg.destination, msg.sensor, C_INTERNAL,
			                      I_NONCE_REQUEST).set(""))) {
				SIGN_DEBUG(PSTR("Failed to transmit nonce request!\n"));
				ret = false;
			} else {
				SIGN_DEBUG(PSTR("Nonce requested from %d. Waiting...\n"), msg.destination);
				// We have to wait for the nonce to arrive before we can sign our original message
				// Other messages could come in-between. We trust _process() takes care of them
				unsigned long enter = hwMillis();
				_msgSign = msg; // Copy the message to sign since message buffer might be touched in _process()
				while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS &&
				        _signingNonceStatus==SIGN_WAITING_FOR_NONCE) {
					_process();
				}
				if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) {
					SIGN_DEBUG(PSTR("Timeout waiting for nonce!\n"));
					ret = false;
				} else {
					if (_signingNonceStatus == SIGN_OK) {
						// process() received a nonce and signerProcessInternal successfully signed the message
						msg = _msgSign; // Write the signed message back
						SIGN_DEBUG(PSTR("Message to send has been signed\n"));
						ret = true;
						// After this point, only the 'last' member of the message structure is allowed to be altered if the
						// message has been signed, or signature will become invalid and the message rejected by the receiver
					} else {
						SIGN_DEBUG(PSTR("Message to send could not be signed!\n"));
						ret = false;
					}
				}
			}
		}
	} else if (getNodeId() == msg.sender) {
		mSetSigned(msg, 0); // Message is not supposed to be signed, make sure it is marked unsigned
		SIGN_DEBUG(PSTR("Will not sign message for destination %d as it does not require it\n"),
		           msg.destination);
		ret = true;
	} else {
		SIGN_DEBUG(PSTR("Will not sign message since it was from %d and we are %d\n"), msg.sender,
		           getNodeId());
		ret = true;
	}
#else
	(void)msg;
	ret = true;
#endif // MY_SIGNING_FEATURE
	return ret;
}
Beispiel #4
0
// Message delivered through _msg
void _processInternalMessages() {
	bool isMetric;
	uint8_t type = _msg.type;

	#if !defined(MY_DISABLE_REMOTE_RESET)
		if (type == I_REBOOT) {
			// Requires MySensors or other bootloader with watchdogs enabled
			hwReboot();
		} else
	#endif
		if (type == I_CONFIG) {
		// Pick up configuration from controller (currently only metric/imperial)
		// and store it in eeprom if changed
	 	if (_msg.getString() == NULL) {
			isMetric = true;
		} else {
			isMetric = _msg.getString()[0] == 'M';
		}
		_cc.isMetric = isMetric;
		hwWriteConfig(EEPROM_CONTROLLER_CONFIG_ADDRESS, isMetric);
	} else if (type == I_PRESENTATION) {
		if (!mGetAck(_msg)) {
			// Re-send node presentation to controller
			#if defined(MY_RADIO_FEATURE)
				transportPresentNode();
			#endif
			if (presentation)
				presentation();
		}
	} else if (type == I_HEARTBEAT) {
		sendHeartbeat();
	} else if (type == I_TIME) {
		// Deliver time to callback
		if (receiveTime)
			receiveTime(_msg.getULong());
	}
	#if defined(MY_REPEATER_FEATURE)
		if (type == I_CHILDREN) {
			if (_msg.getString()[0] == 'C') {
				// Clears child relay data for this node
				debug(PSTR("clear routing table\n"));
				uint8_t i = 255;
				do {
					hwWriteConfig(EEPROM_ROUTES_ADDRESS+i, BROADCAST_ADDRESS);
				} while (i--);
				// Clear parent node id & distance to gw
				hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, AUTO);
				hwWriteConfig(EEPROM_DISTANCE_ADDRESS, DISTANCE_INVALID);
				// Find parent node
				transportFindParentNode();
				_sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN,false).set(""));
			}
		}
	#endif
}
Beispiel #5
0
void nodeLock(const char* str) {
	// Make sure EEPROM is updated to locked status
	hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, 0);
	while (1) {
		debug(PSTR("Node is locked. Ground pin %d and reset to unlock.\n"), MY_NODE_UNLOCK_PIN);
		#if defined(MY_GATEWAY_ESP8266)
			yield();
		#endif
		_sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID,
			C_INTERNAL, I_LOCKED, false).set(str));
		#if defined(MY_RADIO_FEATURE)
			transportPowerDown();
		#endif
		(void)hwSleep((unsigned long)1000*60*30); // Sleep for 30 min before resending LOCKED message
	}
}
Beispiel #6
0
void signerPresentation(MyMessage &msg, uint8_t destination)
{
	prepareSigningPresentation(msg, destination);

#if defined(MY_SIGNING_REQUEST_SIGNATURES)
	msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
	SIGN_DEBUG(PSTR("Signing required\n"));
#endif
#if defined(MY_SIGNING_NODE_WHITELISTING)
	msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
	SIGN_DEBUG(PSTR("Whitelisting required\n"));
#endif

	if (!_sendRoute(msg)) {
		SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n"));
	}

	if (destination == GATEWAY_ADDRESS) {
		SIGN_DEBUG(PSTR("Waiting for GW to send signing preferences...\n"));
		wait(2000, C_INTERNAL, I_SIGNING_PRESENTATION);
	}
}
Beispiel #7
0
// Helper to process presentation mesages
static bool signerInternalProcessPresentation(MyMessage &msg)
{
	const uint8_t sender = msg.sender;
#if defined(MY_SIGNING_FEATURE)
	if (msg.data[0] != SIGNING_PRESENTATION_VERSION_1) {
		SIGN_DEBUG(PSTR("Unsupported signing presentation version (%d)!\n"), msg.data[0]);
		return true; // Just drop this presentation message
	}
	// We only handle version 1 here...
	if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
		// We received an indicator that the sender require us to sign all messages we send to it
		SIGN_DEBUG(PSTR("Mark node %d as one that require signed messages\n"), sender);
		SET_SIGN(sender);
	} else {
		// We received an indicator that the sender does not require us to sign all messages we send to it
		SIGN_DEBUG(PSTR("Mark node %d as one that do not require signed messages\n"), sender);
		CLEAR_SIGN(sender);
	}
	if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
		// We received an indicator that the sender require us to salt signatures with serial
		SIGN_DEBUG(PSTR("Mark node %d as one that require whitelisting\n"), sender);
		SET_WHITELIST(sender);
	} else {
		// We received an indicator that the sender does not require us to sign all messages we send to it
		SIGN_DEBUG(PSTR("Mark node %d as one that do not require whitelisting\n"), sender);
		CLEAR_WHITELIST(sender);
	}

	// Save updated tables
	hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS,
	                   sizeof(_doSign));
	hwWriteConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS,
	                   sizeof(_doWhitelist));

	// Inform sender about our preference if we are a gateway, but only require signing if the sender
	// required signing unless we explicitly configure it to
#if defined(MY_GATEWAY_FEATURE)
	prepareSigningPresentation(msg, sender);
#if defined(MY_SIGNING_REQUEST_SIGNATURES)
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
	msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
#else
	if (DO_SIGN(sender)) {
		msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
	}
#endif
#endif // MY_SIGNING_REQUEST_SIGNATURES
#if defined(MY_SIGNING_NODE_WHITELISTING)
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
	msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
#else
	if (DO_WHITELIST(sender)) {
		msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
	}
#endif
#endif // MY_SIGNING_NODE_WHITELISTING
	if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
		SIGN_DEBUG(PSTR("Informing node %d that we require signatures\n"), sender);
	} else {
		SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures\n"), sender);
	}
	if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
		SIGN_DEBUG(PSTR("Informing node %d that we require whitelisting\n"), sender);
	} else {
		SIGN_DEBUG(PSTR("Informing node %d that we do not require whitelisting\n"), sender);
	}
	if (!_sendRoute(msg)) {
		SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n"));
	}
#endif // MY_GATEWAY_FEATURE
#else // not MY_SIGNING_FEATURE
#if defined(MY_GATEWAY_FEATURE)
	// If we act as gateway and do not have the signing feature and receive a signing request we still
	// need to do make sure the requester does not believe the gateway still require signatures
	prepareSigningPresentation(msg, sender);
	SIGN_DEBUG(
	    PSTR("Informing node %d that we do not require signatures because we do not support it\n"),
	    sender);
	if (!_sendRoute(msg)) {
		SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n"));
	}
#else // not MY_GATEWAY_FEATURE
	// If we act as a node and do not have the signing feature then we just silently drop any signing
	// presentation messages received
	(void)msg;
	(void)sender;
	SIGN_DEBUG(PSTR("Received signing presentation, but signing is not supported (message ignored)\n"));
#endif // not MY_GATEWAY_FEATURE
#endif // not MY_SIGNING_FEATURE 
	return true; // No need to further process I_SIGNING_PRESENTATION
}
Beispiel #8
0
void requestTime() {
	_sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, false).set(""));
}
Beispiel #9
0
void request(uint8_t childSensorId, uint8_t variableType, uint8_t destination) {
	_sendRoute(build(_msg, _nc.nodeId, destination, childSensorId, C_REQ, variableType, false).set(""));
}
Beispiel #10
0
void present(uint8_t childSensorId, uint8_t sensorType, const char *description, bool enableAck) {
	_sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType, enableAck).set(childSensorId==NODE_SENSOR_ID?LIBRARY_VERSION:description));
}
Beispiel #11
0
void sendHeartbeat(void) {
	_sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE, false).set(_heartbeat));

}
Beispiel #12
0
void sendBatteryLevel(uint8_t value, bool enableAck) {
	_sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL, enableAck).set(value));
}
Beispiel #13
0
bool send(MyMessage &message, bool enableAck) {
	message.sender = _nc.nodeId;
	mSetCommand(message,C_SET);
    mSetRequestAck(message,enableAck);
	return _sendRoute(message);
}