コード例 #1
0
ファイル: MCP.cpp プロジェクト: Hukuma23/WS
void MCP::interruptHandler() {
	DEBUG4_PRINTLN("MCP.intH");
	//awakenByInterrupt = true;

	pin = MCP23017::getLastInterruptPin();
	uint8_t last_state = MCP23017::getLastInterruptPinValue();
	uint8_t act_state = MCP23017::digitalRead(pin);

	DEBUG4_PRINTF("push pin=%d state=%d. ", pin, act_state);

	String msg = "push pin= " + String(pin) + ", state= " + String(act_state);
	mqtt->publish("log_mcp_handler", OUT, msg);

	if (act_state == LOW) {
		timerBtnHandle.initializeMs(LONG_TIME, TimerDelegate(&MCP::longtimeHandler, this)).startOnce();
		turnSw(appSettings.getMInNumByPin(pin));

		//String strState = (turnSw(appSettings.getMInNumByPin(pin))?"ON":"OFF");
		//if (mqtt)
		//	mqtt->publish(appSettings.topMIN, appSettings.getMInNumByPin(pin)+1, OUT, strState);
	}
	else {
		attachInterrupt(appSettings.m_int, Delegate<void()>(&MCP::interruptCallback, this), FALLING);
		DEBUG4_PRINTLN();
	}

}
コード例 #2
0
/*
 * Read in a message structure from the serial interface
 */
boolean
hmtl_serial_getmsg(byte *msg, byte msg_len, byte *offset_ptr) 
{
  msg_hdr_t *msg_hdr = (msg_hdr_t *)&msg[0];
  byte offset = *offset_ptr;
  boolean complete = false;

  while (Serial.available()) {
    if (offset > msg_len) {
      /* Offset has exceed the buffer size, start fresh */
      offset = 0;
      DEBUG_ERR("hmtl_serial_update: exceed max msg len");
    }

    byte val = Serial.read();
    //    DEBUG4_VALUE(" ", offset);
    //    DEBUG4_HEXVAL("-", val);

    if (offset == 0) {
      /* Wait for the start code at the beginning of the message */
      if (val != HMTL_MSG_START) {
        DEBUG1_HEXVALLN("hmtl_serial_getmsg: not start code: ",
                        val);
        continue;
      }

      /* This is probably the beginning of the message */ 
    }

    msg[offset] = val;
    offset++;

    if (offset >= sizeof (msg_hdr_t)) {
      /* We have the entire message header */

      if (msg_hdr->length < sizeof (msg_hdr_t)) {
        DEBUG_ERR("hmtl_serial_getmsg: msg length is too short");
        offset = 0;
        continue;
      }

      if (offset == msg_hdr->length) {
        /* This is a complete message */
        DEBUG4_PRINTLN("hmtl_serial_getmsg: Received complete command");
        complete = true;

        // XXX: Check the CRC and the version
        break;
      }
    }
  }

  *offset_ptr = offset;
  return complete;
}
コード例 #3
0
ファイル: MCP.cpp プロジェクト: Hukuma23/WS
void MCP::publish() {
	DEBUG4_PRINT("MCP.publish");

	for (byte i = 0; i < appSettings.msw_cnt; i++) {
		MCP23017::digitalWrite(appSettings.msw[i], actStates.getMsw(i));
		String strState = (actStates.getMsw(i)?"ON":"OFF");
		if (mqtt)
			mqtt->publish(appSettings.topMSW,i+1, OUT, strState);

		DEBUG1_PRINTF("sw[%d]=", i);
		DEBUG1_PRINT(strState);
		DEBUG1_PRINTLN();
	}
	PRINT_MEM();
	DEBUG4_PRINTLN();

	interruptReset();

}
コード例 #4
0
ファイル: MCP.cpp プロジェクト: Hukuma23/WS
void MCP::longtimeHandler() {
	DEBUG4_PRINTLN("MCP.ltH");
	uint8_t act_state = MCP23017::digitalRead(pin);
	while (!(MCP23017::digitalRead(pin)));
	DEBUG4_PRINTF("push pin=%d state=%d. ", pin, act_state);

	byte num = appSettings.getMInNumByPin(pin);
	bool isLong = false;

	if (act_state == LOW) {
		//if (mqtt)
		//	mqtt->publish(appSettings.topMIN_L, num+1, OUT, (actStates.msw[num]?"ON":"OFF"));
		isLong = true;
		DEBUG1_PRINTLN("*-long-*");
	}
	else {
		isLong = false;
		DEBUG1_PRINTLN("*-short-*");
	}

	publish(num, actStates.msw[num], isLong);

	attachInterrupt(appSettings.m_int, Delegate<void()>(&MCP::interruptCallback, this), FALLING);
}
コード例 #5
0
ファイル: MessageHandler.cpp プロジェクト: HMTL/HMTL
/* Process a message if it is for this module */
boolean MessageHandler::process_msg(msg_hdr_t *msg_hdr, Socket *src,
                                    Socket *serial_socket,
                                    config_hdr_t *config) {
  if (msg_hdr->version != HMTL_MSG_VERSION) {
    DEBUG_ERR("Invalid message version");
    return false;
  }

  /* Test if the message is for this device */
  if ((msg_hdr->address == address) ||
      (msg_hdr->address == SOCKET_ADDR_ANY)) {

    if ((msg_hdr->flags & MSG_FLAG_ACK) &&
        (msg_hdr->address != SOCKET_ADDR_ANY)) {
      /*
       * This is an ack message that is not for us, resend it over serial in
       * case that was the original source.
       * TODO: Maybe this should check address as well, and serial needs to be
       * assigned an address?
       */
      DEBUG4_PRINTLN("Forwarding ack to serial");
      Serial.write((byte *)msg_hdr, msg_hdr->length);

      if (msg_hdr->type != MSG_TYPE_SENSOR) { // Sensor broadcasts are for everyone
        return false;
      }
    }

    switch (msg_hdr->type) {

      case MSG_TYPE_OUTPUT: {
        output_hdr_t *out_hdr = (output_hdr_t *)(msg_hdr + 1);
        if (out_hdr->type == HMTL_OUTPUT_PROGRAM) {
          manager->handle_msg((msg_program_t *)out_hdr);
        } else {
          hmtl_handle_output_msg(msg_hdr, manager->num_outputs,
                                 manager->outputs, manager->objects);
        }

        return true;
      }

      case MSG_TYPE_POLL: {
        // Generate a response to a poll message
        uint16_t source_address = 0;
        Socket *sock;

        if (src != NULL) {
          // The response will be going over a socket, get the source address
          source_address = src->sourceFromData(msg_hdr);
          sock = src;
        } else {
          // The data will be sent back to the indicated Serial device.  A
          // socket still needs to be specified in order to have a buffer to
          // fill.
          sock = serial_socket;
        }

        DEBUG3_VALUELN("Poll req src:", source_address);

        // Format the poll response
        uint16_t len = hmtl_poll_fmt(sock->send_buffer,
                                     sock->send_data_size,
                                     source_address,
                                     msg_hdr->flags, OBJECT_TYPE,
                                     config,
                                     manager->outputs,
                                     sock->recvLimit);

        // Respond to the appropriate source
        if (src != NULL) {
          if (msg_hdr->address == SOCKET_ADDR_ANY) {
            // If this was a broadcast address then do not respond immediately,
            // delay for time based on our address.
            int delayMs = address * 2;
            DEBUG3_VALUELN("Delay resp: ", delayMs)
            delay(delayMs); // TODO: This blocks any running program?  Use a timer
          }

          src->sendMsgTo(source_address, sock->send_buffer, len);
        } else {
          // Send the response on the serial device
          Serial.write(sock->send_buffer, len);
        }

        break;
      }

      case MSG_TYPE_SET_ADDR: {
        /* Handle an address change message */
        msg_set_addr_t *set_addr = (msg_set_addr_t *)(msg_hdr + 1);
        if ((set_addr->device_id == 0) ||
            (set_addr->device_id == config->device_id)) {
          address = set_addr->address;
          src->sourceAddress = address;
          DEBUG2_VALUELN("Address changed to ", address);
        }
        break;
      }

      case MSG_TYPE_SENSOR: {
        if (msg_hdr->flags & MSG_FLAG_ACK) {
          /*
           * This is a sensor response, record relevant values for usage
           * elsewhere.
           */
          msg_sensor_data_t *sensor = NULL;
          while ((sensor = hmtl_next_sensor(msg_hdr, sensor))) {
            // Call the ProgramManager's handler for the sensor function
            manager->run_program(PROGRAM_SENSOR_DATA, sensor);
          }
          DEBUG_PRINT_END();
        }
        break;
      }

      case MSG_TYPE_TIMESYNC: {
        /*
         * This is a time synchronization message, send to the ProgramManager's
         * TimeSync object.
         */
        timesync.synchronize(src, SOCKET_ADDR_INVALID, msg_hdr);
        break;
      }

      case MSG_TYPE_DUMP_CONFIG: {
        /*
         * This is a request to dump the EEPROM objects to the serial device.
         *
         * TODO: This could be made to work remotely rather than only to requests
         * from the serial device.
         */
        uint16_t source_address = 0;

        DEBUG3_VALUELN("Dump req src:", source_address);

        /*
         * The response will be a typical message header followed by the raw data
         * from EEPROM.
         */
        msg_dumpconfig_response_t *resp = (msg_dumpconfig_response_t *)(serial_socket->send_buffer + sizeof (msg_hdr_t));

        int location = HMTL_CONFIG_ADDR; // Starting location in EEPROM
        int next_addr = 0;
        uint8_t flags;

        do {
          uint16_t len;
          flags = msg_hdr->flags;

          next_addr = EEPROM_safe_read(location, resp->data,
                                       serial_socket->send_data_size -
                                           HMTL_MSG_DUMPCONFIG_MIN_LEN);
          if (next_addr > 0) {
            uint16_t datalen = (uint16_t)EEPROM_DATA_SIZE(next_addr - location);

            DEBUG4_VALUELN("Dump config:", location);

            /*
             * Check if the next address is a valid structure and if so indicate
             * that there will be additional messages.
             */
            if (EEPROM_check_address(next_addr)) {
              flags |= MSG_FLAG_MORE_DATA;
            } else {
              DEBUG4_PRINTLN("Dump final message")
            }

            // Now that the length of the data is known construct the message
            len = hmtl_dumpconfig_fmt(serial_socket->send_buffer,
                                      serial_socket->send_data_size,
                                      source_address,
                                      flags,
                                      datalen);

            location = next_addr;
          } else {
            /*
             * There was an error, respond with an error flag
             */
            flags |= MSG_FLAG_ERROR;

            len = hmtl_dumpconfig_fmt(serial_socket->send_buffer,
                                      serial_socket->send_data_size,
                                      source_address,
                                      flags,
                                      0);
          }

          Serial.write(serial_socket->send_buffer, len);

        } while (flags & MSG_FLAG_MORE_DATA);

        break;
      }
    }
  }
コード例 #6
0
ファイル: MCP.cpp プロジェクト: Hukuma23/WS
MCP::~MCP() {
	DEBUG4_PRINTLN("MCP delete called");
}
コード例 #7
0
ファイル: MCP.cpp プロジェクト: Hukuma23/WS
void MCP::start() {
	DEBUG4_PRINTLN("MCP::start");
	timer.initializeMs(appSettings.interval_mcp, TimerDelegate(&MCP::publish,this)).start();
}
コード例 #8
0
ファイル: MCP.cpp プロジェクト: Hukuma23/WS
void MCP::stopTimer() {
	DEBUG4_PRINTLN("MCP::stopTimer");
	timer.stop();
};
コード例 #9
0
ファイル: MCP.cpp プロジェクト: Hukuma23/WS
void MCP::startTimer() {
	DEBUG4_PRINTLN("MCP::startTimer");
	timer.initializeMs(appSettings.shift_mcp, TimerDelegate(&MCP::start, this)).startOnce();
};
コード例 #10
0
ファイル: ProgramManager.cpp プロジェクト: HMTL/HMTL
/*
 * Process a program configuration message
 */
boolean ProgramManager::handle_msg(msg_program_t *msg) {
  DEBUG4_VALUE("handle_msg: program=", msg->type);
  DEBUG4_VALUELN(" output=", msg->hdr.output);

  /* Find the program to be executed */
  byte program = lookup_function(msg->type);
  if (program == NO_PROGRAM) {
    DEBUG1_VALUELN("handle_msg: invalid type: ", msg->type);
    return false;
  }

  /* Setup the tracker */
  int starting_output, stop_output;

  if (msg->hdr.output == HMTL_ALL_OUTPUTS) {
    /* This should be applied to all outputs that can handle the message type */
    starting_output = 0;
    stop_output = num_outputs;
  } else if (msg->hdr.output > num_outputs) {
    DEBUG1_VALUELN("handle_msg: invalid output: ",
                   msg->hdr.output);
    return false;
  } else if (outputs[msg->hdr.output] == NULL) {
    DEBUG1_VALUELN("handle_msg: NULL output: ", msg->hdr.output);
    return false;
  } else {
    /* Only apply to the specified output */
    starting_output = msg->hdr.output;
    stop_output = starting_output + 1;
  }

  for (int output = starting_output; output < stop_output; output++) {

    if (outputs[output] == NULL)
      continue;

    if (msg->type == HMTL_PROGRAM_NONE) {
      /* This is a message to clear the existing program so free the tracker */
      DEBUG3_VALUELN("handle_msg: clear ", output);
      free_tracker(output);
      continue;
    }

    program_tracker_t *tracker;
    if (functions[program].program == NULL) {
      /*
       * This is an initialization-only command, set tracker to null
       */
      DEBUG4_PRINTLN("handle_msg: trackerless")
      tracker = NULL;
    } else {
      /* If there was an active program on this output then clear the tracker */
      free_tracker(output);

      /* Setup a tracker for this program */
      tracker = get_tracker(output);
      tracker->program_index = program;
      tracker->flags = 0x0;
    }

    if (tracker) {
      // Record the output and object in the tracker
      tracker->output = outputs[output];
      tracker->object = objects[output];
    }

    /* Attempt to setup the program */


    boolean success = functions[program].setup(msg, tracker, outputs[output],
                                               objects[output], this);

    if (!success) {
      if (tracker) {
        DEBUG4_VALUELN("handle_msg: NA on ", output);
        free_tracker(output);
      }
      continue;
    }
    DEBUG4_VALUELN("handle_msg: setup on ", output);
  }

  return true;
}
コード例 #11
0
/* Initialized the pins of an output */
int hmtl_setup_output(config_hdr_t *config, output_hdr_t *hdr, void *data)
{
  DEBUG4_VALUE("hmtl_setup_output: type=", hdr->type);
  switch (hdr->type) {
    case HMTL_OUTPUT_VALUE: 
      {
        config_value_t *out = (config_value_t *)hdr;
        DEBUG4_PRINT(" value");
        pinMode(out->pin, OUTPUT);
        break;
      }
    case HMTL_OUTPUT_RGB:
      {
        config_rgb_t *out = (config_rgb_t *)hdr;
        DEBUG4_PRINT(" rgb");
        for (int j = 0; j < 3; j++) {
          pinMode(out->pins[j], OUTPUT);
        }
        break;
      }
    case HMTL_OUTPUT_PROGRAM:
      {
        //        config_program_t *out = (config_program_t *)hdr;
        DEBUG4_PRINT(" program");
        break;
      }
#ifdef USE_PIXELUTIL
    case HMTL_OUTPUT_PIXELS:
      {
        DEBUG4_PRINT(" pixels");
        if (data != NULL) {
          config_pixels_t *out = (config_pixels_t *)hdr;
          PixelUtil *pixels = (PixelUtil *)data;
          pixels->init(out->numPixels,
                       out->dataPin,
                       out->clockPin,
                       out->type);
        } else {
          DEBUG_ERR("Expected PixelUtil data struct for pixel configs");
          return -1;
        }
        break;
      }
#endif
#ifdef USE_MPR121
    case HMTL_OUTPUT_MPR121:
      {
        DEBUG4_PRINTLN(" mpr121");
        if (data != NULL) {
          config_mpr121_t *out = (config_mpr121_t *)hdr;
          MPR121 *capSensor = (MPR121 *)data;
          capSensor->init(out->irqPin,
                          out->useInterrupt,
                          START_ADDRESS,  // XXX - Only single address
                          false,          // XXX - No touch times
                          false);         // XXX - No auto enable
          for (int i = 0; i < MAX_MPR121_PINS; i++) {
            byte touch = out->thresholds[i] & 0x0F;
            byte release = (out->thresholds[i] & 0xF0) >> 4;
            if (touch || release) {
              capSensor->setThreshold(i, touch, release);
            }
          }
        } else {
          DEBUG_ERR("Expected MPR121 data struct for mpr121 configs");
          return -1;
        }
        break;
      }