#include "app.h" #include #include // http://bleaklow.com/2010/09/05/progmem_and_gcc_bug_34734.html #undef PROGMEM #define PROGMEM __attribute__((section(".progmem.data"))) #define SENSOR_COUNT 2 // See http://redbearlab.com/blendmicro/ for pins. struct sm_sensor { uint8_t a_pin; uint8_t d1_pin; uint8_t d2_pin; uint16_t value; uint16_t warning_value; uint16_t update_interval; uint8_t name_length; char name[SENSOR_NAME_LEN]; } sensors[SENSOR_COUNT] = { // A Pin, D1 Pin, D2 Pin, Value, Warning Value, Update Interval, Length of Name, Name { 8, 3, 5, 0, 10, 0, 9, "Sensor #1"}, { 10, 11, 12, 0, 10, 0, 9, "Sensor #2"}, }; static unsigned long next_update[SENSOR_COUNT]; void sm_on_connect() { // Disable all updates until enabled. for (int i = 0; i < SENSOR_COUNT; i++) { next_update[i] = 0; } } void sm_setup() { for (int i = 0; i < SENSOR_COUNT; i++) { struct sm_sensor s = sensors[i]; pinMode(s.a_pin, INPUT); pinMode(s.d1_pin, OUTPUT); pinMode(s.d2_pin, OUTPUT); } } void sm_loop() { static unsigned long last = 0, now; static uint8_t x = 10; now = millis(); if (now - last > 3000) { last = now; for (int i = 0; i < SENSOR_COUNT; i++) { struct sm_sensor& s = sensors[i]; digitalWrite(s.d1_pin, HIGH); digitalWrite(s.d2_pin, LOW); s.value = analogRead(s.a_pin); Serial.print("#"); Serial.print(i, DEC); Serial.print(" = "); Serial.print(s.value, DEC); Serial.println(); } } // TODO: implement proper notification if (false && now - last > 3000) { last = now; struct sm_res res; res.code = SM_CMD_GET_VALUE; res.get_value.value = x; x++; if(x == 0) { x = 10; } // if(x % 2 == 0) { // notify_soil_moisture(res); // } else { // notify_battery_level(x); // } notify_soil_moisture(res, sizeof(sm_get_value_res)); } } #ifdef SM_DEBUG static void write_name(uint8_t const* name, uint8_t len) { for(int i = 0; i < len; i++) { Serial.print((char)name[i]); } } void write_req(struct sm_req const& req) { Serial.print(">> "); switch(req.code) { case SM_CMD_GET_SENSOR_COUNT: Serial.print("SM_CMD_GET_SENSOR_COUNT"); break; case SM_CMD_GET_VALUE: Serial.print("SM_CMD_GET_VALUE"); Serial.print(": sensor="); Serial.print(req.get_value.sensor, DEC); break; case SM_CMD_SET_WARNING_VALUE: Serial.print("SM_CMD_SET_WARNING_VALUE"); Serial.print(": sensor="); Serial.print(req.set_warning_value.sensor, DEC); Serial.print(", warning_value="); Serial.print(req.set_warning_value.warning_value, DEC); break; case SM_CMD_GET_WARNING_VALUE: Serial.print("SM_CMD_GET_WARNING_VALUE"); Serial.print(": sensor="); Serial.print(req.get_warning_value.sensor, DEC); break; case SM_CMD_SET_SENSOR_NAME: Serial.print("SM_CMD_SET_SENSOR_NAME"); Serial.print(": sensor="); Serial.print(req.set_sensor_name.sensor, DEC); Serial.print(", name="); write_name(req.set_sensor_name.name, req.set_sensor_name.length); break; case SM_CMD_GET_SENSOR_NAME: Serial.print("SM_CMD_GET_SENSOR_NAME"); break; case SM_CMD_SET_UPDATE_INTERVAL: Serial.print("SM_CMD_SET_UPDATE_INTERVAL"); Serial.print(": interval_in_seconds="); Serial.print(req.set_update_interval.interval_in_seconds, DEC); break; default: Serial.print("Unknown command!"); } Serial.println(); } void write_res(struct sm_res const& res) { Serial.print("<< "); switch(res.code) { case SM_CMD_GET_SENSOR_COUNT: Serial.print("SM_CMD_GET_SENSOR_COUNT"); Serial.print(": count="); Serial.print(res.get_sensor_count.count, DEC); break; case SM_CMD_GET_VALUE: Serial.print("SM_CMD_GET_VALUE"); Serial.print(": value="); Serial.print(res.get_value.value, DEC); break; case SM_CMD_SET_WARNING_VALUE: Serial.print("SM_CMD_SET_WARNING_VALUE"); break; case SM_CMD_GET_WARNING_VALUE: Serial.print("SM_CMD_GET_WARNING_VALUE"); Serial.print(": warning_value="); Serial.print(res.get_warning_value.warning_value, DEC); break; case SM_CMD_SET_SENSOR_NAME: Serial.print("SM_CMD_SET_SENSOR_NAME"); break; case SM_CMD_GET_SENSOR_NAME: Serial.print("SM_CMD_GET_SENSOR_NAME"); Serial.print(": name="); write_name(res.get_sensor_name.name, res.get_sensor_name.length); break; case SM_CMD_SET_UPDATE_INTERVAL: Serial.print("SM_CMD_SET_UPDATE_INTERVAL"); break; default: Serial.print("Unknown command!"); } Serial.println(); } #endif void on_soil_moisture_ctrl(uint8_t *data, uint8_t len) { struct sm_req *req = (struct sm_req *) data; struct sm_res res; uint8_t sensor; #if SM_DEBUG == 1 write_req(*req); #endif res.code = req->code; uint8_t body_len; switch(req->code) { case SM_CMD_GET_SENSOR_COUNT: body_len = sizeof(sm_get_sensor_count_res); res.get_sensor_count.count = SENSOR_COUNT; break; case SM_CMD_GET_VALUE: body_len = sizeof(sm_get_value_res); sensor = req->get_value.sensor; if (sensor < SENSOR_COUNT) { // TODO: update the sensor's value res.get_value.value = sensors[sensor].value; } else { res.code = SM_CMD_FAIL; } break; case SM_CMD_SET_WARNING_VALUE: body_len = sizeof(sm_set_warning_value_res); sensor = req->set_warning_value.sensor; if (sensor < SENSOR_COUNT) { sensors[sensor].warning_value = req->set_warning_value.warning_value; } else { res.code = SM_CMD_FAIL; } break; case SM_CMD_GET_WARNING_VALUE: body_len = sizeof(sm_get_warning_value_res); sensor = req->get_warning_value.sensor; if (sensor < SENSOR_COUNT) { res.get_warning_value.warning_value = sensors[sensor].warning_value; } else { res.code = SM_CMD_FAIL; } break; case SM_CMD_SET_SENSOR_NAME: body_len = sizeof(sm_set_sensor_name_res); sensor = req->set_sensor_name.sensor; if (sensor < SENSOR_COUNT) { sensors[sensor].name_length = min(req->set_sensor_name.length, SENSOR_NAME_LEN); memcpy(sensors[sensor].name, req->set_sensor_name.name, sensors[sensor].name_length); } else { res.code = SM_CMD_FAIL; } break; case SM_CMD_GET_SENSOR_NAME: body_len = sizeof(sm_get_sensor_name_res); sensor = req->get_sensor_name.sensor; if (sensor < SENSOR_COUNT) { res.get_sensor_name.length = sensors[sensor].name_length; memcpy(res.get_sensor_name.name, sensors[sensor].name, SENSOR_NAME_LEN); } else { res.code = SM_CMD_FAIL; } break; case SM_CMD_SET_UPDATE_INTERVAL: body_len = sizeof(sm_set_update_interval_res); sensor = req->set_update_interval.sensor; if (sensor < SENSOR_COUNT) { sensors[sensor].update_interval = req->set_update_interval.interval_in_seconds; } else { res.code = SM_CMD_FAIL; } break; default: body_len = 0; res.code = SM_CMD_FAIL; break; } if (res.code == SM_CMD_FAIL) { body_len = 0; } notify_soil_moisture(res, body_len); }