Exemplo n.º 1
0
uint8_t wkpf_propagate_property(wuobject_t *wuobject, uint8_t property_number, void *value) {
	uint8_t port_number = wuobject->port_number;
	uint16_t component_id;
	if (!wkpf_get_component_id(port_number, &component_id))
		return WKPF_OK; // WuObject isn't used in the application.

	wuobject_t *src_wuobject;
	uint8_t wkpf_error_code;

	DEBUG_LOG(DBG_WKPF, "WKPF: propagate property number %x of component %x on port %x (value %x)\n", property_number, component_id, port_number, *((uint16_t *)value)); // TODONR: values other than 16 bit values

	wkpf_get_wuobject_by_port(port_number, &src_wuobject);
	for(int i=0; i<wkpf_number_of_links; i++) {
		wkpf_link_t *link = wkpf_get_link(i);
		if(link->src_component_id == component_id
				&& link->src_property_number == property_number) {
			uint16_t dest_component_id = link->dest_component_id;
			uint8_t dest_property_number = link->dest_property_number;
			uint8_t dest_port_number = wkpf_leader_for_component(dest_component_id).port_number;
			address_t dest_node_id = wkpf_leader_for_component(dest_component_id).node_id;
			if (dest_node_id == wkcomm_get_node_id()) {
				// Local
				wuobject_t *dest_wuobject;
				wkpf_error_code = wkpf_get_wuobject_by_port(dest_port_number, &dest_wuobject);
				if (wkpf_error_code == WKPF_OK) {
					DEBUG_LOG(DBG_WKPF, "WKPF: propagate_property (local). (%x, %x)->(%x, %x), value %x\n", port_number, property_number, dest_port_number, dest_property_number, *((uint16_t *)value)); // TODONR: values other than 16 bit values
					if (WKPF_GET_PROPERTY_DATATYPE(src_wuobject->wuclass->properties[property_number]) == WKPF_PROPERTY_TYPE_BOOLEAN)
						wkpf_error_code = wkpf_external_write_property_boolean(dest_wuobject, dest_property_number, *((bool *)value));
					else if (WKPF_GET_PROPERTY_DATATYPE(src_wuobject->wuclass->properties[property_number]) == WKPF_PROPERTY_TYPE_SHORT)
						wkpf_error_code = wkpf_external_write_property_int16(dest_wuobject, dest_property_number, *((uint16_t *)value));
					else
						wkpf_error_code = wkpf_external_write_property_refresh_rate(dest_wuobject, dest_property_number, *((uint16_t *)value));
				}
			} else {
				// Remote
				DEBUG_LOG(DBG_WKPF, "WKPF: propagate_property (remote). (%x, %x)->(%x, %x, %x), value %x\n", port_number, property_number, dest_node_id, dest_port_number, dest_property_number, *((uint16_t *)value)); // TODONR: values other than 16 bit values
				if (WKPF_GET_PROPERTY_DATATYPE(src_wuobject->wuclass->properties[property_number]) == WKPF_PROPERTY_TYPE_BOOLEAN)
					wkpf_error_code = wkpf_send_set_property_boolean(dest_node_id, dest_port_number, dest_property_number, link->dest_wuclass_id, *((bool *)value));
				else if (WKPF_GET_PROPERTY_DATATYPE(src_wuobject->wuclass->properties[property_number]) == WKPF_PROPERTY_TYPE_SHORT)
					wkpf_error_code = wkpf_send_set_property_int16(dest_node_id, dest_port_number, dest_property_number, link->dest_wuclass_id, *((uint16_t *)value));
				else
					wkpf_error_code = wkpf_send_set_property_refresh_rate(dest_node_id, dest_port_number, dest_property_number, link->dest_wuclass_id, *((uint16_t *)value));
			}
			if (wkpf_error_code != WKPF_OK)
				return wkpf_error_code;
		}
	}
	return WKPF_OK;
}
uint8_t wkpf_create_wuobject(uint16_t wuclass_id, uint8_t port_number, dj_object *java_instance_reference /* TODO: find out what datatype to use */ ) {
	wuobject_t *wuobject;
	if (wkpf_get_wuobject_by_port(port_number, &wuobject) != WKPF_ERR_WUOBJECT_NOT_FOUND) {
		DEBUG_LOG(DBG_WKPF, "WKPF: Port %x in use while creating wuobject for wuclass id %x: FAILED\n", port_number, wuclass_id);
		return WKPF_ERR_PORT_IN_USE;
	}

	// Find the wuclass definition for this wuclass_id
	wuclass_t *wuclass;
	uint8_t retval;
	retval = wkpf_get_wuclass_by_id(wuclass_id, &wuclass);
	if (retval != WKPF_OK)
		return retval;

	// Check if an instance of the wuclass is provided if it's a virtual wuclass
	if (WKPF_IS_VIRTUAL_WUCLASS(wuclass) && java_instance_reference==0)
		return WKPF_ERR_NEED_VIRTUAL_WUCLASS_INSTANCE;

	// Allocate memory for the new wuobject
	uint8_t size_of_properties = 0;
	for(int i=0; i<wuclass->number_of_properties; i++) {
		size_of_properties += WKPF_GET_PROPERTY_DATASIZE(wuclass->properties[i]);
	}
	uint16_t size = sizeof(wuobject_t) + size_of_properties; // TODO: add space for the properties;
	dj_mem_addSafePointer((void**)&java_instance_reference); // dj_mem_alloc may cause GC to run, so the address of the wuclass and the virtual wuclass instance may change. this tells the GC to update our pointer if it does.
	dj_mem_addSafePointer((void**)&wuclass); // dj_mem_alloc may cause GC to run, so the address of the wuclass and the virtual wuclass instance may change. this tells the GC to update our pointer if it does.
	wuobject = (wuobject_t*)dj_mem_alloc(size, CHUNKID_WUCLASS);
	dj_mem_removeSafePointer((void**)&java_instance_reference);
	dj_mem_removeSafePointer((void**)&wuclass);
	if (wuobject == NULL) {
		DEBUG_LOG(DBG_WKPF, "WKPF: Out of memory while creating wuobject for wuclass %x at port %x: FAILED\n", wuclass_id, port_number);
		return WKPF_ERR_OUT_OF_MEMORY;
	}

	// Initialise memory (fixes a bug where old data corrupted the property status)
	memset(wuobject, 0, size);

	// Check if any properties need to pull their initial value from a remote node (properties that are the destination end of a link coming from another node)
	for(int i=0; i<wuclass->number_of_properties; i++) {
		if (wkpf_does_property_need_initialisation_pull(port_number, i)) {
			wuobject_property_t *property = wkpf_get_property(wuobject, i);
			wkpf_set_property_status_needs_pull(property);
			DEBUG_LOG(DBG_WKPF, "WKPF: Setting needs pull bit for property %x at port %x\n", i, port_number);
		}
	}

	wuobject->wuclass = wuclass;
	wuobject->port_number = port_number;
	wuobject->java_instance_reference = java_instance_reference;
	wuobject->need_to_call_update = false;
	if (retval != WKPF_OK)
		return retval;
	// Run update function once to initialise properties.
	wkpf_set_need_to_call_update_for_wuobject(wuobject);

	wuobject->next = wuobjects_list;
	wuobjects_list = wuobject;
	DEBUG_LOG(DBG_WKPF, "WKPF: Created wuobject for wuclass id %x at port %x\n", wuclass_id, port_number);
	return WKPF_OK;
}
void javax_wukong_wkpf_WKPF_void_setPropertyRefreshRate_short_byte_short() {
	int16_t value = (int16_t)dj_exec_stackPopShort();
	uint8_t property_number = (uint8_t)dj_exec_stackPopShort();
	uint16_t component_id = (uint16_t)dj_exec_stackPopShort();
	address_t node_id;
	uint8_t port_number;
	wkpf_error_code = wkpf_get_node_and_port_for_component(component_id, &node_id, &port_number);
	if (wkpf_error_code == WKPF_OK) {
		if (node_id != wkcomm_get_node_id())
			wkpf_error_code = WKPF_ERR_REMOTE_PROPERTY_FROM_JAVASET_NOT_SUPPORTED;
		else {
			wuobject_t *wuobject;
			wkpf_error_code = wkpf_get_wuobject_by_port(port_number, &wuobject);
			if (wkpf_error_code == WKPF_OK) {
				DEBUG_LOG(DBG_WKPF, "WKPF: setPropertyRefreshRate (local). Port %x, property %x, value %x\n", port_number, property_number, value);
				wkpf_error_code = wkpf_external_write_property_refresh_rate(wuobject, property_number, value);
			}
		}
	}
}
Exemplo n.º 4
0
//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
Exemplo n.º 5
0
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) {