예제 #1
0
void onLedReturnFadeLimits()
{
	cmdMessenger.sendCmdStart(kRLedFadeMinMax);
	cmdMessenger.sendCmdArg(ledFadeTargetMin);
	cmdMessenger.sendCmdArg(ledFadeTargetMax);
	cmdMessenger.sendCmdEnd();
}
예제 #2
0
void onReturnDeviceInfo()
{
	cmdMessenger.sendCmdStart(kRDeviceInfo);
	cmdMessenger.sendCmdArg(APP_FW_VER);
	cmdMessenger.sendCmdArg(EEPROM.readInt(64));
	cmdMessenger.sendCmdEnd();
}
/**
 * This method must be called regularily within the loop() function
 */
void deviceUpdate() {
  // Blink the LED

  if (device->ledPin > 0) {
    if (blinkPattern && millis() > blinkMillis) {
      digitalWrite(device->ledPin, digitalRead(device->ledPin) == HIGH ? LOW : HIGH);
      ++blinkIndex;
      if (blinkPattern[blinkIndex] == 0) {
        blinkIndex = 0;
      }
      blinkMillis = millis() + blinkPattern[blinkIndex];
    }
  }

  // State machine

  switch (state) {

    case STATE_INIT:
      // --------------------------------------------------------------------------------
      // Initial state after powering up

      DEBUG_PRINTLN_STATE(F("INIT"))

#ifdef AUTO_CONFIG
      if (device->buttonPin > 0) {
        if (digitalRead(device->buttonPin) == LOW) {
          activateBlinkPattern(factoryResetBlinkPattern);
          timeoutMillis = millis() + WAIT_FOR_FACTORYRESET_TIMEOUT;
          state = STATE_FACTORY_RESET_CONFIRM;
          break;
        }
      }
#endif

      magic = EEPROM.readInt(EEPROM_MAGIC_ADDR);
      if (magic != MAGIC_NUMBER) {
#ifdef AUTO_CONFIG
        state = STATE_NEW_DEVICE;
#else
        state = STATE_INIT;
#endif
        break;
      }

      DEBUG_PRINTLN(F("Valid EEPROM Data"))
      EEPROM.readBlock(EEPROM_DEVICE_UUID_ADDR, deviceUuid, DEVICE_UUID_LEN);
      EEPROM.readBlock(EEPROM_DEVICE_NAME_ADDR, deviceName, DEVICE_NAME_MAX_LEN);
      EEPROM.readBlock(EEPROM_SSID_ADDR, ssid, SSID_MAX_LEN);
      EEPROM.readBlock(EEPROM_PHRASE_ADDR, phrase, PHRASE_MAX_LEN);
      DEBUG_DUMP_CONFIG_VALUES()
      state = STATE_CONNECT_WLAN;
      break;

#ifdef AUTO_CONFIG
    case STATE_FACTORY_RESET_CONFIRM:
      // --------------------------------------------------------------------------------
      // User must press the button WAIT_FOR_FACTORYRESET_TIMEOUT seconds
      // before the factory reset is actually executed

      DEBUG_PRINTLN_STATE(F("FACTORY_RESET_CONFIRM"))
      if (device->buttonPin > 0) {
        if (digitalRead(device->buttonPin) == HIGH) {
          // Factory reset was cancelled
          delay(10);
          activateBlinkPattern(NULL);
          state = STATE_INIT;
        } else if (millis() > timeoutMillis) {
          state = STATE_FACTORY_RESET;
        }
      }
      break;
#endif

#ifdef AUTO_CONFIG
    case STATE_FACTORY_RESET:
      // --------------------------------------------------------------------------------
      // Perform a factory reset

      DEBUG_PRINTLN_STATE(F("FACTORY_RESET"))
      for (int i = 0; i < EEPROM_SIZE; ++i) {
        EEPROM.writeByte(i, 0xff);
      }
      activateBlinkPattern(NULL);
      state = STATE_INIT;
      break;
#endif

#ifdef AUTO_CONFIG
    case STATE_NEW_DEVICE:
      // --------------------------------------------------------------------------------
      // Entered if this is a new device with no stored valid EEPROM data

      DEBUG_PRINTLN_STATE(F("NEW_DEVICE"))
      activateBlinkPattern(newDeviceBlinkPattern);
      wifly.reset();
      wifly.sendCommand("set u b " MAKE_STRING(WIFLY_BAUDRATE) "\r");
      wifly.sendCommand("get m\r", "Mac Addr=");
      wifly.receive((uint8_t *) mac, 17);
      mac[17] = '\0';
      DEBUG_PRINT(F("- MAC: "))
      DEBUG_PRINTLN(mac)
      DEBUG_PRINTLN(F("- Activate AP mode"))
      wifly.sendCommand("set w j 7\r", "OK"); // Enable AP mode
      wifly.sendCommand("set w c 6\r", "OK");
      sprintf(buf, "set a s Caretaker-%c%c%c%c%c%c%c%c%c%c%c%c\r", mac[0], mac[1], mac[3], mac[4], mac[6], mac[7],
          mac[9], mac[10], mac[12], mac[13], mac[15], mac[16]);
      wifly.sendCommand(buf, "OK");
      wifly.sendCommand("set a p 0347342d\r", "OK");
      wifly.sendCommand("set i d 4\r", "OK"); // Enable DHCP server
      wifly.sendCommand("set i a 192.168.0.1\r", "OK");
      wifly.sendCommand("set i n 255.255.255.0\r", "OK");
      wifly.sendCommand("set i g 192.168.0.1\r", "OK");
      wifly.save();
      wifly.reboot();
      state = STATE_WAIT_FOR_DISCOVERY;
      break;
#endif

#ifdef AUTO_CONFIG
    case STATE_WAIT_FOR_DISCOVERY:
      // --------------------------------------------------------------------------------
      // Wait until the configuration app has opened a connection to this device

      DEBUG_PRINTLN_STATE(F("WAIT_FOR_DISCOVERY"))
      if (checkWiflyInput("*OPEN*")) {
        activateBlinkPattern(discoveredBlinkPattern);
        state = STATE_SEND_INFO;
      }
      break;
#endif

#ifdef AUTO_CONFIG
    case STATE_SEND_INFO:
      // --------------------------------------------------------------------------------
      // Send information about this device to the configuration app

      DEBUG_PRINTLN_STATE(F("SEND_INFO"))
      wifly.println(); // Other side receives "*HELLO*\n"
      wifly.println(mac);
      wifly.println(device->type);
      wifly.println(device->description);
      state = STATE_WAIT_FOR_SEND_INFO_ACK;
      break;
#endif

#ifdef AUTO_CONFIG
    case STATE_WAIT_FOR_SEND_INFO_ACK:
      // --------------------------------------------------------------------------------
      // Wait for the receiving confirmation

      DEBUG_PRINTLN_STATE(F("WAIT_FOR_SEND_INFO_ACK"))
      if (checkWiflyInput("*CLOS*")) {
        timeoutMillis = millis() + WAIT_FOR_CONFIG_TIMEOUT;
        state = STATE_WAIT_FOR_CONFIG;
      }
      break;
#endif

#ifdef AUTO_CONFIG
    case STATE_WAIT_FOR_CONFIG:
      // --------------------------------------------------------------------------------
      // Configuration app has WAIT_FOR_CONFIG_TIMEOUT seconds to send the configuration

      DEBUG_PRINTLN_STATE(F("WAIT_FOR_CONFIG"))
      if (checkWiflyInput("*OPEN*")) {
        state = STATE_CONFIGURE_DEVICE;
      } else if (millis() > timeoutMillis) {
        state = STATE_CONFIG_TIMEOUT;
      }
      break;
#endif

#ifdef AUTO_CONFIG
    case STATE_CONFIG_TIMEOUT:
      // --------------------------------------------------------------------------------
      // No configuration received, restart discovery process

      DEBUG_PRINTLN_STATE(F("CONFIG_TIMEOUT"))
      state = STATE_NEW_DEVICE;
      break;
#endif

#ifdef AUTO_CONFIG
    case STATE_CONFIGURE_DEVICE:
      // --------------------------------------------------------------------------------
      // Read and store the confifuration values

      DEBUG_PRINTLN_STATE(F("CONFIGURE_DEVICE"))
      wifly.println(); // Other side receives "*HELLO*\n"
      if (!(wiflyReadline(deviceUuid, DEVICE_UUID_LEN))) {
        state = STATE_CONFIG_TIMEOUT;
        break;
      }
      if (!(wiflyReadline(deviceName, DEVICE_NAME_MAX_LEN))) {
        state = STATE_CONFIG_TIMEOUT;
        break;
      }
      if (!(wiflyReadline(ssid, SSID_MAX_LEN))) {
        state = STATE_CONFIG_TIMEOUT;
        break;
      }
      if (!(wiflyReadline(phrase, PHRASE_MAX_LEN))) {
        state = STATE_CONFIG_TIMEOUT;
        break;
      }

      while (!checkWiflyInput("*CLOS*")) {
      }

      DEBUG_DUMP_CONFIG_VALUES()

      EEPROM.writeInt(EEPROM_MAGIC_ADDR, MAGIC_NUMBER);
      EEPROM.writeBlock(EEPROM_DEVICE_UUID_ADDR, deviceUuid, DEVICE_UUID_LEN);
      EEPROM.writeBlock(EEPROM_DEVICE_NAME_ADDR, deviceName, DEVICE_NAME_MAX_LEN);
      EEPROM.writeBlock(EEPROM_SSID_ADDR, ssid, SSID_MAX_LEN);
      EEPROM.writeBlock(EEPROM_PHRASE_ADDR, phrase, PHRASE_MAX_LEN);

      activateBlinkPattern(NULL);
      state = STATE_CONNECT_WLAN;
      break;
#endif

    case STATE_CONNECT_WLAN:
      // --------------------------------------------------------------------------------
      // Connect to the configured WLAN and start sending broadcast messages

      DEBUG_PRINTLN_STATE(F("CONNECT_WLAN"))
      wifly.reset();
      wifly.sendCommand("set u b " MAKE_STRING(WIFLY_BAUDRATE) "\r");
      wifly.sendCommand("set i h 0.0.0.0\r", "OK"); // UDP auto pairing
      wifly.sendCommand("set i f 0x40\r", "OK"); // UDP auto pairing
      wifly.sendCommand("set i d 1\r", "OK"); // DHCP client on
      wifly.sendCommand("set i p 1\r", "OK"); // Use UDP
      wifly.sendCommand("set b i 7\r", "OK"); // UDP broadcast interval 8 secs
#ifdef BROADCAST_PORT
          wifly.sendCommand("set b p 44444\r", "OK"); // Set broadcast port to 44444 when debugging
#endif
      wifly.sendCommand("set w a 4\r", "OK");
      wifly.sendCommand("set w c 0\r", "OK");
      wifly.sendCommand("set w j 1\r", "OK");
      snprintf(buf, BUF_LEN, "set w s %s\r", ssid);
      wifly.sendCommand(buf, "OK");
      snprintf(buf, BUF_LEN, "set w p %s\r", phrase);
      wifly.sendCommand(buf, "OK");
      snprintf(buf, BUF_LEN, "set o d %s\r", deviceName);
      wifly.sendCommand(buf, "OK");
      wifly.save();
      wifly.reboot();
      state = STATE_WAIT_FOR_BROADCAST_RESPONSE;
      break;

    case STATE_WAIT_FOR_BROADCAST_RESPONSE:
      // --------------------------------------------------------------------------------
      // Wait until the broadcast receiver sends a broadcast response with the actual
      // with server IP address

      DEBUG_PRINTLN_STATE(F("WAIT_FOR_BROADCAST_RESPONSE"))
      if (checkWiflyInput("*SERVER*\n")) {
        if (wiflyReadline(serverAddress, SERVER_ADDRESS_LEN)) {
          snprintf(buf, BUF_LEN, "- Broadcast response from server: %s", serverAddress);
          DEBUG_PRINTLN(buf);
          // Set the server IP address for UDP transmissions
          // Disable UDP broadcast
          snprintf(buf, BUF_LEN, "set i h %s\r", serverAddress);
          wifly.sendCommand(buf, "OK");
          wifly.sendCommand("set b i 0\r", "OK");
          wifly.save();
          wifly.dataMode();
          state = STATE_REGISTER_WITH_SERVER;
        }
      }
      break;

    case STATE_REGISTER_WITH_SERVER:
      // --------------------------------------------------------------------------------
      // Send a registration request to the server, containing all device information:

      DEBUG_PRINTLN_STATE(F("REGISTER_WITH_SERVER"))
      messenger.sendCmdStart(MSG_REGISTER_REQUEST);
      messenger.sendCmdArg(deviceUuid);
      messenger.sendCmdArg(device->type);
      messenger.sendCmdArg(deviceName);
      messenger.sendCmdArg(device->description);
      if (device->sendServerRegisterParams) {
        (*device->sendServerRegisterParams)();
      }
      messenger.sendCmdEnd();
      timeoutMillis = millis() + WAIT_FOR_REGISTRATION_TIMEOUT;
      state = STATE_WAIT_FOR_REGISTER_WITH_SERVER_RESPONSE;
      break;

    case STATE_WAIT_FOR_REGISTER_WITH_SERVER_RESPONSE:
      // --------------------------------------------------------------------------------
      // Wait until the server responds to our registration request

      DEBUG_PRINTLN_STATE(F("WAIT_FOR_REGISTER_WITH_SERVER_RESPONSE"))
      if (millis() > timeoutMillis) {
        state = STATE_REGISTER_WITH_SERVER;
      } else {
        messenger.feedinSerialData();
      }
      break;

    case STATE_OPERATIONAL:
      // --------------------------------------------------------------------------------
      // Normal operational mode

      DEBUG_PRINTLN_STATE(F("OPERATIONAL"))
      if (millis() > nextPingMillis) {
        messenger.sendCmd(MSG_PING);
        nextPingMillis = millis() + PING_INTERVAL;
      }
      messenger.feedinSerialData();
      break;
  }
}