예제 #1
0
void process_command()
{
  DEBUG_PRINTLN("process_command");
  DEBUG_PRINTLN2("command ", command.command);
  DEBUG_PRINTLN2H("com.addr  ", command.node_id.addr);
  DEBUG_PRINTLN2H("this.addr ", THIS_NODE);

  answer.node_id.addr = THIS_NODE;
  answer.command = command.command;
  answer.number = command.number;
  answer.answer = 0;

  if (command.node_id.addr == THIS_NODE ||
    command.node_id.addr == 0)
  {

    switch(command.command)
    {
      case ECommand_LIGHT_ON:
      {
        DEBUG_PRINTLN("ECommand_LIGHT_ON");
        //digitalWrite(ledPin, HIGH);
        // digitalWrite(ledPin, LOW);
        current_color = 7;
        set_led(true);

        answer.answer = 1;

        break;
      }
      case ECommand_LIGHT_OFF:
      {
        DEBUG_PRINTLN("ECommand_LIGHT_OFF");
        // digitalWrite(ledPin, LOW);
        // digitalWrite(ledPin, HIGH);
        set_led(false);


        answer.answer = 2;

        break;
      }
      case ECommand_BEACON:
      {
        // answer is ready for beacon, no processing needed
        DEBUG_PRINTLN("ECommand_BEACON");
        break;
      }
      default:
      {
        answer.answer = -1;
      }
    }

    send_package(SimpleAnswer_fields, &answer, packet_xb_writer);
  }

}
예제 #2
0
extern "C" int8_t fsm_parse(fsm const* f, unsigned long timeout, uint8_t parse_error)
{
	DEBUG_PRINTLN("fsm_parse");
	uint8_t state = 0;
	uint8_t newstate = 0;
	int8_t action;
	unsigned long begin_time = millis();
	while (1)
	{
		if (f->gen->avail(f->gen->avail_param))
		{
			char c = f->gen->next(f->gen->next_param);
			DEBUG_PRINTLN2("c = ", c);
			uint8_t cls = get_class(f, c);
			DEBUG_PRINTLN2("cls = ", cls);
			DEBUG_PRINTLN2("state = ", (int)newstate);
			if (cls != f->classes_count)
				newstate = f->table[state * f->states_count + cls];
			else
				newstate = -1;

			DEBUG_PRINTLN2("newstate = ", (int)newstate);

			if (-1 == newstate)
			{
				newstate = 0;
				if (parse_error)
					return FSM_PARSE_ERR;
			}
			action = get_action(f, state, newstate);
			DEBUG_PRINTLN2("action = ", action);
			if (action != FSM_NOTHING)
			{
				DEBUG_PRINTLN("WTF");
				return action;
			}

			if (millis() - begin_time > timeout)
				return FSM_TIMEOUT;

			state = newstate;
		}
	}
}
예제 #3
0
static void set_led(bool on)
{
#define ON(color) ((current_color & color) ? LOW : HIGH)
#define OFF(color) HIGH
#define SWITCH(on, color) (on ? ON(color) : OFF(color))

  DEBUG_PRINTLN2("set_led ", on);
  DEBUG_PRINTLN2("color ", current_color);

  current_enabled = on;
  digitalWrite(RED_LED, SWITCH(on, 4));
  digitalWrite(GREEN_LED, SWITCH(on, 2));
  digitalWrite(BLUE_LED, SWITCH(on, 1));


#undef SWITCH
#undef OFF
#undef ON
}
예제 #4
0
void process_ZB_TX_STATUS_RESPONSE()
{
  DEBUG_PRINTLN("process_ZB_TX_STATUS_RESPONSE");

  sent = true;
  sent_ok = mrf.get_txinfo()->tx_ok;

  DEBUG_PRINTLN2("tx ", sent_ok ? "ok" : "err");
  DEBUG_PRINTLN2H("rc ", mrf.get_txinfo()->retries);
}
예제 #5
0
void process_position_notify()
{
  DEBUG_PRINTLN("process_position_notify");
  DEBUG_PRINTLN2H("pos_notify.addr ", pos_notify.node_id.addr);
  DEBUG_PRINTLN2("pos_notify.x ", pos_notify.x);
  DEBUG_PRINTLN2("pos_notify.y ", pos_notify.y);

  uint8_t x = pos_notify.x;
  uint8_t y = pos_notify.y;

  for (uint8_t i = 0; i < sizeof(colors) / sizeof(colors[0]); ++i)
  {
    ColorRect& r = colors[i];
    if (r.l <= x && x <= r.r &&
        r.t <= y && y <= r.b)
    {
      current_color = r.color;
      set_led(current_enabled);
      DEBUG_PRINTLN2("set color ", current_color);
      break;
    }
  }
}
예제 #6
0
void process_ZB_RX_RESPONSE()
{
  uint8_t* data = mrf.get_rxinfo()->rx_data;
  uint8_t const length = mrf.rx_datalength();

  DEBUG_PRINTLN2("process_ZB_RX_RESPONSE length = ", length);
  for (int i =0;i < length; ++i)
  {
    Serial.print(data[i], HEX);
    Serial.print(' ');
  }
  DEBUG_PRINTLN(' ');

  send_dst_addr = mrf.get_rxinfo()->src_addr16;

  pb_istream_t istream = pb_istream_from_buffer(data, length);

  process_incoming_packet(&istream);
}
예제 #7
0
bool process_incoming_packet(pb_istream_t* isrt)
{
  bool status = false;

  const pb_field_t *type = decode_unionmessage_type(isrt, MessagePackage_fields);

  if (SimpleCommand_fields == type)
  {
    status = decode_unionmessage_contents(isrt, SimpleCommand_fields, &command);
    if (status)
      process_command();
  }
  else if (SimpleAnswer_fields == type)
  {
    status = decode_unionmessage_contents(isrt, SimpleAnswer_fields, &answer);
    if (status)
      process_answer();
  }
  else if (DebugPrint_fields == type)
  {
    status = decode_unionmessage_contents(isrt, DebugPrint_fields, &debug_print_message);
    if (status)
      process_debug_print_package();
  }
  else if  (PositionNotify_fields == type)
  {
    status = decode_unionmessage_contents(isrt, PositionNotify_fields, &pos_notify);
    if (status)
      process_position_notify();
  }
  else
  {
    // Serial.println("Unknown package");
    // ERROR_BLINK(9);
  }

  if (!status)
  {
    DEBUG_PRINTLN2("process_incoming_packet error ", PB_GET_ERROR(isrt));
  }

  return status;
}
예제 #8
0
bool packet_xb_writer(uint8_t* data, uint8_t size)
{
  DEBUG_PRINTLN2("packet_xb_writer", (int)size);

  sent = false;
  sent_ok = false;

  const char* pd = (char*)data;
  mrf.send16(send_dst_addr, pd, size);

  unsigned long now = millis();

  do
  {
    DEBUG_PRINTLN("packet_xb_writer waiting");
    process_mrf_packets();
  } while (!sent);

  DEBUG_PRINTLN("packet_xb_writer done");

  return sent_ok;
}
/**************************************************************************
 *
 *   Handles low level ACI events, and passes them up to an application
 *   level callback when appropriate
 *
 **************************************************************************/
void GoosciBleGatt::pollACI() {
  static bool setup_required = false;

  // We enter the if statement only when there is a ACI event
  // available to be processed
  if (lib_aci_event_get(&aci_state, &aci_data)) {
    aci_evt_t *aci_evt;
    aci_evt = &aci_data.evt;
    // DEBUG_PRINTLN(F("pollACI"));
    // DEBUG_PRINT("evt opcode: ");
    // DEBUG_PRINTLN2(aci_evt->evt_opcode, HEX);
    // DEBUG_PRINT(F("State Total credit: "));
    // DEBUG_PRINTLN(aci_state.data_credit_total);
    // DEBUG_PRINT(F("State Available credit: "));
    // DEBUG_PRINTLN(aci_state.data_credit_available);
    // DEBUG_PRINT("Event Available credit: ");
    // DEBUG_PRINTLN(aci_evt->params.device_started.credit_available);
    switch (aci_evt->evt_opcode) {
      case ACI_EVT_DEVICE_STARTED: {
	// DEBUG_PRINTLN("STARTED");
        aci_state.data_credit_total =
            aci_evt->params.device_started.credit_available;
        switch (aci_evt->params.device_started.device_mode) {
          case ACI_DEVICE_SETUP: {
	    // DEBUG_PRINTLN("SETUP");
            aci_state.device_state = ACI_DEVICE_SETUP;
            setup_required = true;
            break;
          }

          case ACI_DEVICE_STANDBY: {
	    // DEBUG_PRINTLN("STANDBY");
            aci_state.device_state = ACI_DEVICE_STANDBY;

            // sleep_to_wakeup_timeout = 30;

            if (aci_evt->params.device_started.hw_error) {
              // Magic number used to make sure the HW error
              // event is handled correctly.
              delay(20);
            } else {
	      get_address();
	      // DEBUG_PRINTLN("lib_aci_connect");
              lib_aci_connect(adTimeout, adInterval);
            }
            break;
          }
          case ACI_DEVICE_INVALID: {
            DEBUG_PRINTLN(F("Evt Device Invalid"));
            break;
          }

          case ACI_DEVICE_TEST: {
            break;
          }

          case ACI_DEVICE_SLEEP: {
            break;
          }
        }
        break;  // case ACI_EVT_DEVICE_STARTED:
      }

      case ACI_EVT_CMD_RSP: {
        DEBUG_PRINTLN("ACI_EVT_CMD_RSP");
        // If an ACI command response event comes with an error -> stop
        if (ACI_STATUS_SUCCESS != aci_evt->params.cmd_rsp.cmd_status) {
          // ACI ReadDynamicData and ACI WriteDynamicData
          // will have status codes of
          // TRANSACTION_CONTINUE and TRANSACTION_COMPLETE
          // all other ACI commands will have status code of
          // ACI_STATUS_SCUCCESS for a successful command
          DEBUG_PRINT(F("ACI Command 0x"));
          DEBUG_PRINTLN2(aci_evt->params.cmd_rsp.cmd_opcode, HEX);
          DEBUG_PRINT(F("Evt Cmd response: Error. "));
          DEBUG_PRINTLN2(aci_evt->params.cmd_rsp.cmd_status, HEX);
        }
        if (ACI_CMD_GET_DEVICE_ADDRESS == aci_evt->params.cmd_rsp.cmd_opcode) {
          // If this is a response to get device address, save the address
          addrReceived = true;
          // DEBUG_PRINT(F("Get device address response: "));
          for (int i = BTLE_DEVICE_ADDRESS_SIZE - 1; i >= 0; --i) {
            deviceAddress[i] = aci_evt->params.cmd_rsp.params.get_device_address
                .bd_addr_own[i];
            //   DEBUG_PRINT2(deviceAddress[i], HEX);
            //   DEBUG_PRINT(F(":"));
          }
          // DEBUG_PRINTLN(F(""));
        } else if (ACI_CMD_OPEN_ADV_PIPE ==
                   aci_evt->params.cmd_rsp.cmd_opcode) {
          DEBUG_PRINTLN(
              F("Open advertising pipe response, setting service data."));
          lib_aci_set_local_data(
              &aci_state, PIPE_DEVICE_INFORMATION_MODEL_NUMBER_STRING_BROADCAST,
              (unsigned char *)longName, 8);
          DEBUG_PRINT(F("Advertising starting for "));
          DEBUG_PRINTLN(deviceName);
          lib_aci_connect(adTimeout, adInterval);
        } else if (ACI_CMD_GET_DEVICE_VERSION == aci_evt->params.cmd_rsp.cmd_opcode) {
          DEBUG_PRINTLN("ACI_CMD_GET_DEVICE_VERSION");
        } else if (ACI_CMD_SET_LOCAL_DATA == aci_evt->params.cmd_rsp.cmd_opcode) {
          DEBUG_PRINTLN("ACI_CMD_SET_LOCAL_DATA");
        } else if (ACI_CMD_CONNECT == aci_evt->params.cmd_rsp.cmd_opcode) {
          DEBUG_PRINTLN("ACI_CMD_CONNECT");
        } else if (ACI_CMD_DISCONNECT == aci_evt->params.cmd_rsp.cmd_opcode) {
          DEBUG_PRINTLN("ACI_CMD_DISCONNECT");
        } else if (ACI_CMD_CHANGE_TIMING == aci_evt->params.cmd_rsp.cmd_opcode) {
          DEBUG_PRINTLN("ACI_CMD_CHANGE_TIMING");
        }  else {
          // print command
          DEBUG_PRINT(F("Unexpected ACI Command 0x"));
          DEBUG_PRINTLN2(aci_evt->params.cmd_rsp.cmd_opcode, HEX);
        }
        break;
      }

      case ACI_EVT_CONNECTED: {
        // The nRF8001 is now connected to the peer device.
        DEBUG_PRINTLN(F("Evt Connected"));
        aci_state.data_credit_available = aci_state.data_credit_total;
        timing_change_done = false;
        break;
      }

      case ACI_EVT_PIPE_STATUS: {
        DEBUG_PRINTLN(F("Evt Pipe Status: "));
        // DEBUG_PRINT2((int) aci_evt->params.pipe_status.pipes_open_bitmap, HEX);
        // DEBUG_PRINT(" ");
        // DEBUG_PRINTLN2((int) aci_evt->params.pipe_status.pipes_closed_bitmap, HEX);
        if (lib_aci_is_pipe_available(&aci_state, PIPE_GOOSCI_SENSOR_VALUE_TX) && !timing_change_done) {
          lib_aci_change_timing(6, 6, 0, 600); // Low-latency parameters
        timing_change_done = true;
      }

        break;
      }

      case ACI_EVT_TIMING: {
        // DEBUG_PRINT("ACI_EVT_TIMING: ");
        // DEBUG_PRINT(aci_evt->params.timing.conn_rf_interval);
        // DEBUG_PRINT(" ");
        // DEBUG_PRINT(aci_evt->params.timing.conn_slave_rf_latency);
        // DEBUG_PRINT(" ");
        // DEBUG_PRINT(aci_evt->params.timing.conn_rf_timeout);
		// DEBUG_PRINT(" ");
        // DEBUG_PRINTLN(aci_evt->params.timing.conn_rf_interval);
        break;
      }

      case ACI_EVT_DISCONNECTED: {
        // Advertise again if the advertising timed out.
        DEBUG_PRINTLN(F("Evt Disconnected."));
        // TODO(dek): figure out why the transition to using credits
        // broke disconnection (packets are still transmitted).
        // Setting the credits to 0 was an experiment but it didn't work.
        // aci_state.data_credit_available = 0; 
        lib_aci_connect(adTimeout, adInterval);
        timing_change_done = false;
        break;
      }

      case ACI_EVT_DATA_RECEIVED: {
	DEBUG_PRINTLN("ACI_EVT_DATA_RECEIVED");
        if (aci_evt->params.data_received.rx_data.pipe_number == PIPE_GOOSCI_SENSOR_CONFIGURATION_RX_ACK_AUTO) {
          int8_t packet_length = aci_evt->len;
	  handle(aci_evt->params.data_received.rx_data.aci_data, aci_evt->len);
	} else {
	  DEBUG_PRINT(F(" Data(Hex) : "));
	  for (int i = 0; i < aci_evt->len - 2; i++) {
	    DEBUG_PRINT2(aci_evt->params.data_received.rx_data.aci_data[i], HEX);
	    DEBUG_PRINT(F(" "));
	  }
	  DEBUG_PRINTLN(F(""));
	}
	break;
      }


      case ACI_EVT_DATA_CREDIT: {
        // DEBUG_PRINTLN(F("Evt Credit: Peer has received our send"));
        aci_state.data_credit_available = aci_state.data_credit_available + aci_evt->params.data_credit.credit;
        break;
      }

      case ACI_EVT_PIPE_ERROR: {
        // See the appendix in the nRF8001
        // Product Specication for details on the error codes
        DEBUG_PRINT(F("ACI Evt Pipe Error: Pipe #:"));
        DEBUG_PRINT2(aci_evt->params.pipe_error.pipe_number, DEC);
        DEBUG_PRINT(F("  Pipe Error Code: 0x"));
        DEBUG_PRINTLN2(aci_evt->params.pipe_error.error_code, HEX);

        // Increment the credit available as the data packet was not sent.
        // The pipe error also represents the Attribute protocol
        // Error Response sent from the peer and that should not be counted
        // for the credit.
        if (ACI_STATUS_ERROR_PEER_ATT_ERROR !=
            aci_evt->params.pipe_error.error_code) {
          aci_state.data_credit_available++;
        }
        break;
      }

      case ACI_EVT_DATA_ACK: {
        // DEBUG_PRINTLN(F("ACK"));
        break;
      }
      case ACI_EVT_HW_ERROR: {
        DEBUG_PRINTLN(F("HW error: "));
        DEBUG_PRINTLN2(aci_evt->params.hw_error.line_num, DEC);

        for (int counter = 0; counter <= (aci_evt->len - 3); counter++) {
          DEBUG_PRINT(aci_evt->params.hw_error.file_name[counter]);
        }
        DEBUG_PRINTLN();
        initLocalData();
        lib_aci_connect(adTimeout, adInterval);
        break;
      }

      default: {
        DEBUG_PRINT(F("Evt Opcode 0x"));
        DEBUG_PRINT2(aci_evt->evt_opcode, HEX);
        DEBUG_PRINTLN(F(" unhandled"));
        break;
      }
    }
  }

  // setup_required is set to true when the device starts
  // up and enters setup mode.
  // It indicates that do_aci_setup() should be called.
  // The flag should be cleared if do_aci_setup() returns
  // ACI_STATUS_TRANSACTION_COMPLETE.
  if (setup_required) {
    int result = do_aci_setup(&aci_state);
    if (result != SETUP_SUCCESS ) {
      switch(result) {
        case SETUP_FAIL_COMMAND_QUEUE_NOT_EMPTY:
          DEBUG_PRINTLN("SETUP_FAIL_COMMAND_QUEUE_NOT_EMPTY");
          break;
        case SETUP_FAIL_EVENT_QUEUE_NOT_EMPTY:
          DEBUG_PRINTLN("SETUP_EVENT_COMMAND_QUEUE_NOT_EMPTY");
          break;
        case SETUP_FAIL_NOT_SETUP_EVENT:
          DEBUG_PRINTLN("SETUP_FAIL_NOT_SETUP_EVENT");
          break;
        case SETUP_FAIL_NOT_COMMAND_RESPONSE:
          DEBUG_PRINTLN("SETUP_FAIL_NOT_COMMAND_RESPONSE");
          break;
      }
    } else {
      setup_required = false;
    }
  }
}