//void wkpf_comm_handle_message(wkcomm_address_t src, uint8_t nvmcomm_command, uint8_t *payload, uint8_t response_size, uint8_t response_cmd) { void wkpf_comm_handle_message(void *data) { wkcomm_received_msg *msg = (wkcomm_received_msg *)data; uint8_t *payload = msg->payload; uint8_t response_size = 0, response_cmd = 0; uint8_t retval; if (dj_exec_getRunlevel() == RUNLEVEL_REPROGRAMMING) return; switch (msg->command) { case WKPF_COMM_CMD_GET_LOCATION: { // Format of get_location request messages: payload[0] offset of the first byte requested // Format of get_location return messages: payload[0..] the part of the location string // The length of the location is stored by the master as the first byte of the string. // Get the offset of the requested data within the location string uint8_t requested_offset = payload[0]; // Read the EEPROM uint8_t length = wkpf_config_get_part_of_location_string((char *)payload, requested_offset, WKCOMM_MESSAGE_PAYLOAD_SIZE); DEBUG_LOG(DBG_WKPF, "WKPF_COMM_CMD_GET_LOCATION: Reading %d bytes at offset %d\n", length, requested_offset); response_cmd = WKPF_COMM_CMD_GET_LOCATION_R; response_size = length; } break; case WKPF_COMM_CMD_SET_LOCATION: { // Format of set_location request messages: payload[0] offset of part of the location string being sent // Format of set_location request messages: payload[1] the length of part of the location string being sent // Format of set_location request messages: payload[2..] the part of the location string // Format of set_location return messages: payload[0] the wkpf return code uint8_t written_offset = payload[0]; uint8_t length = payload[1]; DEBUG_LOG(DBG_WKPF, "WKPF_COMM_CMD_SET_LOCATION: Writing %d bytes at offset %d\n", length, written_offset); // Read the EEPROM retval = wkpf_config_set_part_of_location_string((char*) payload+2, written_offset, length); // Send response if (retval == WKPF_OK) { response_cmd = WKPF_COMM_CMD_SET_LOCATION_R; } else { response_cmd = WKPF_COMM_CMD_ERROR_R; } payload[0] = retval; response_size = 1; } break; case WKPF_COMM_CMD_GET_FEATURES: { int count = 0; for (int i=0; i<WKPF_NUMBER_OF_FEATURES; i++) { // Needs to be changed if we have more features than fits in a single message, but for now it will work fine. if (wkpf_config_get_feature_enabled(i)) { payload[1+count++] = i; } } payload[0] = count; response_cmd = WKPF_COMM_CMD_GET_FEATURES_R; response_size = 1+count; } break; case WKPF_COMM_CMD_SET_FEATURE: { retval = wkpf_config_set_feature_enabled(payload[2], payload[3]); if (retval == WKPF_OK) { response_cmd = WKPF_COMM_CMD_SET_FEATURE_R; response_size = 0; } else { payload[2] = retval; response_cmd = WKPF_COMM_CMD_ERROR_R; response_size = 1; } } break; case WKPF_COMM_CMD_GET_WUCLASS_LIST: { // Request format: payload[0] request message number // Response format: payload[0] response message number // Response format: payload[1] total number of messages // Response format: payload[2] number of wuclasses uint8_t number_of_wuclasses = wkpf_get_number_of_wuclasses(); uint8_t number_of_messages = (number_of_wuclasses / NUMBER_OF_WUCLASSES_PER_MESSAGE); if ((number_of_wuclasses % NUMBER_OF_WUCLASSES_PER_MESSAGE) != 0) number_of_messages++; uint8_t start_at_wuclass_index = payload[0]*NUMBER_OF_WUCLASSES_PER_MESSAGE; payload[1] = number_of_messages; payload[2] = number_of_wuclasses; uint8_t number_of_wuclasses_in_message = number_of_wuclasses - start_at_wuclass_index; if (number_of_wuclasses_in_message > NUMBER_OF_WUCLASSES_PER_MESSAGE) number_of_wuclasses_in_message = NUMBER_OF_WUCLASSES_PER_MESSAGE; for (uint8_t i=0; i<number_of_wuclasses_in_message; i++) { wuclass_t *wuclass; wkpf_get_wuclass_by_index(i+start_at_wuclass_index, &wuclass); payload[3*i + 3] = (uint8_t)(wuclass->wuclass_id >> 8); payload[3*i + 4] = (uint8_t)(wuclass->wuclass_id); if (wuclass->flags & WKPF_WUCLASS_FLAG_APP_CAN_CREATE_INSTANCE) { payload[3*i + 5] = WKPF_IS_VIRTUAL_WUCLASS(wuclass) ? 3 : 2; } else { payload[3*i + 5] = WKPF_IS_VIRTUAL_WUCLASS(wuclass) ? 1 : 0; } } response_size = 3*number_of_wuclasses_in_message + 3; // 3*wuclasses + 3 bytes for message nr, number of messages, number of wuclasses response_cmd = WKPF_COMM_CMD_GET_WUCLASS_LIST_R; } break; case WKPF_COMM_CMD_GET_WUOBJECT_LIST: { // Request format: payload[0] request message number // Response format: payload[0] response message number // Response format: payload[1] total number of messages // Response format: payload[2] number of wuobjects uint8_t number_of_wuobjects = wkpf_get_number_of_wuobjects(); uint8_t number_of_wuobject_messages = (number_of_wuobjects / NUMBER_OF_WUOBJECTS_PER_MESSAGE); if ((number_of_wuobjects % NUMBER_OF_WUOBJECTS_PER_MESSAGE) != 0) number_of_wuobject_messages++; uint8_t start_at_wuobject_index = payload[0]*NUMBER_OF_WUOBJECTS_PER_MESSAGE; payload[1] = number_of_wuobject_messages; payload[2] = number_of_wuobjects; uint8_t number_of_wuobjects_in_message = number_of_wuobjects - start_at_wuobject_index; if (number_of_wuobjects_in_message > NUMBER_OF_WUOBJECTS_PER_MESSAGE) number_of_wuobjects_in_message = NUMBER_OF_WUOBJECTS_PER_MESSAGE; for (uint8_t i=0; i<number_of_wuobjects_in_message; i++) { wuobject_t *wuobject; wkpf_get_wuobject_by_index(start_at_wuobject_index+i, &wuobject); payload[4*i + 3] = (uint8_t)(wuobject->port_number); payload[4*i + 4] = (uint8_t)(wuobject->wuclass->wuclass_id >> 8); payload[4*i + 5] = (uint8_t)(wuobject->wuclass->wuclass_id); payload[4*i + 6] = WKPF_IS_VIRTUAL_WUCLASS(wuobject->wuclass); } response_size = 4*number_of_wuobjects_in_message + 3; // 4*wuobjects + 3 bytes for message nr, number of messages, number of wuobjects (max 39 bytes, barely over 40 bytes) response_cmd = WKPF_COMM_CMD_GET_WUOBJECT_LIST_R; } break; case WKPF_COMM_CMD_READ_PROPERTY: { // TODONR: check wuclassid uint8_t port_number = payload[0]; // TODONR: uint16_t wuclass_id = (uint16_t)(payload[1]<<8)+(uint16_t)(payload[2]); uint8_t property_number = payload[3]; wuobject_t *wuobject; retval = wkpf_get_wuobject_by_port(port_number, &wuobject); if (retval != WKPF_OK) { payload [2] = retval; response_cmd = WKPF_COMM_CMD_ERROR_R; response_size = 1; break; } uint8_t property_status; wkpf_get_property_status(wuobject, property_number, &property_status); if (WKPF_GET_PROPERTY_DATATYPE(wuobject->wuclass->properties[property_number]) == WKPF_PROPERTY_TYPE_SHORT) { int16_t value; retval = wkpf_external_read_property_int16(wuobject, property_number, &value); payload[4] = WKPF_GET_PROPERTY_DATATYPE(wuobject->wuclass->properties[property_number]); payload[5] = property_status; payload[6] = (uint8_t)(value>>8); payload[7] = (uint8_t)(value); response_size = 8; response_cmd = WKPF_COMM_CMD_READ_PROPERTY_R; } else if (WKPF_GET_PROPERTY_DATATYPE(wuobject->wuclass->properties[property_number]) == WKPF_PROPERTY_TYPE_BOOLEAN) { bool value; retval = wkpf_external_read_property_boolean(wuobject, property_number, &value); payload[4] = WKPF_GET_PROPERTY_DATATYPE(wuobject->wuclass->properties[property_number]); payload[5] = property_status; payload[6] = (uint8_t)(value); response_size = 7; response_cmd = WKPF_COMM_CMD_READ_PROPERTY_R; } else if (WKPF_GET_PROPERTY_DATATYPE(wuobject->wuclass->properties[property_number]) == WKPF_PROPERTY_TYPE_REFRESH_RATE) { wkpf_refresh_rate_t value; retval = wkpf_external_read_property_refresh_rate(wuobject, property_number, &value); payload[4] = WKPF_GET_PROPERTY_DATATYPE(wuobject->wuclass->properties[property_number]); payload[5] = property_status; payload[6] = (uint8_t)(value>>8); payload[7] = (uint8_t)(value); response_size = 8; response_cmd = WKPF_COMM_CMD_READ_PROPERTY_R; } else
void wkpf_comm_handle_message(u08_t nvmcomm_command, u08_t *payload, u08_t *response_size, u08_t *response_cmd) { uint8_t number_of_wuclasses; uint8_t number_of_wuobjects; // TODONR: uint16_t wuclass_id; uint8_t port_number; uint8_t property_number; uint8_t retval; wkpf_local_wuobject *wuobject; if (nvm_runlevel != NVM_RUNLVL_VM) return; switch (nvmcomm_command) { case NVMCOMM_WKPF_GET_LOCATION: payload[2] = strlen(location); strcpy((char*)payload+3, location); *response_size = sizeof(location) + 3;//payload size location + 2 byte overhead + 1 byte location size *response_cmd = NVMCOMM_WKPF_GET_LOCATION_R; break; case NVMCOMM_WKPF_SET_LOCATION: strncpy(location, (char*)payload+3, payload[2]); *response_size = 6; *response_cmd = NVMCOMM_WKPF_SET_LOCATION_R; retval = WKPF_OK; if (retval != WKPF_OK) { payload[2] = retval; *response_size = 3;//payload size *response_cmd = NVMCOMM_WKPF_ERROR_R; } break; case NVMCOMM_WKPF_GET_WUCLASS_LIST: number_of_wuclasses = wkpf_get_number_of_wuclasses(); payload[2] = number_of_wuclasses; for (int i=0; i<number_of_wuclasses && i<9; i++) { // TODONR: i<9 is temporary to keep the length within MESSAGE_SIZE, but we should have a protocol that sends multiple messages wkpf_wuclass_definition *wuclass; wkpf_get_wuclass_by_index(i, &wuclass); payload[3*i + 3] = (uint8_t)(wuclass->wuclass_id >> 8); payload[3*i + 4] = (uint8_t)(wuclass->wuclass_id); payload[3*i + 5] = WKPF_IS_VIRTUAL_WUCLASS(wuclass) ? 1 : 0; } *response_size = 3*number_of_wuclasses + 3;//payload size 2*wuclasses + 2 bytes seqnr + 1 byte number of wuclasses *response_cmd = NVMCOMM_WKPF_GET_WUCLASS_LIST_R; break; case NVMCOMM_WKPF_GET_WUOBJECT_LIST: number_of_wuobjects = wkpf_get_number_of_wuobjects(); payload[2] = number_of_wuobjects; for (int i=0; i<number_of_wuobjects && i<9; i++) { // TODONR: i<9 is temporary to keep the length within MESSAGE_SIZE, but we should have a protocol that sends multiple messages wkpf_local_wuobject *wuobject; wkpf_get_wuobject_by_index(i, &wuobject); payload[3*i + 3] = (uint8_t)(wuobject->port_number); payload[3*i + 4] = (uint8_t)(wuobject->wuclass->wuclass_id >> 8); payload[3*i + 5] = (uint8_t)(wuobject->wuclass->wuclass_id); } *response_size = 3*number_of_wuobjects + 3;//payload size 3*wuobjects + 2 bytes seqnr + 1 byte number of wuclasses *response_cmd = NVMCOMM_WKPF_GET_WUOBJECT_LIST_R; break; case NVMCOMM_WKPF_READ_PROPERTY: // TODONR: check wuclassid port_number = payload[2]; // TODONR: wuclass_id = (uint16_t)(payload[3]<<8)+(uint16_t)(payload[4]); property_number = payload[5]; retval = wkpf_get_wuobject_by_port(port_number, &wuobject); if (retval != WKPF_OK) { payload [2] = retval; *response_cmd = NVMCOMM_WKPF_ERROR_R; *response_size = 3;//payload size break; } uint8_t property_status; wkpf_get_property_status(wuobject, property_number, &property_status); if (WKPF_GET_PROPERTY_DATATYPE(wuobject->wuclass->properties[property_number]) == WKPF_PROPERTY_TYPE_SHORT) { int16_t value; retval = wkpf_external_read_property_int16(wuobject, property_number, &value); payload[6] = WKPF_GET_PROPERTY_DATATYPE(wuobject->wuclass->properties[property_number]); payload[7] = property_status; payload[8] = (uint8_t)(value>>8); payload[9] = (uint8_t)(value); *response_size = 10;//payload size *response_cmd = NVMCOMM_WKPF_READ_PROPERTY_R; } else if (WKPF_GET_PROPERTY_DATATYPE(wuobject->wuclass->properties[property_number]) == WKPF_PROPERTY_TYPE_BOOLEAN) {