From e4d28ae72e086dce1bc31c50105be9cf56c238a3 Mon Sep 17 00:00:00 2001 From: Baptiste Gaultier Date: Tue, 31 Mar 2015 21:17:35 +0200 Subject: [PATCH] Stable release : laboite v3.4 (modular code in progress) --- laboite.ino | 156 +++++++++++++++++++++++++++----------------- laboiteLib.ino | 174 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 251 insertions(+), 79 deletions(-) diff --git a/laboite.ino b/laboite.ino index d56a3a9..2ee7d23 100644 --- a/laboite.ino +++ b/laboite.ino @@ -1,12 +1,13 @@ /* - laboite v3.2.23.2.2 + laboite v3.4 This Arduino firmware is part of laboite project https://laboite.cc/help It is a connected device displaying a lot of information (A LOT !) coming from an Internet server with a laboite web app deployed (e.g. https://laboite.cc/ ). Key Features: - * Connects to laboite-webapp to retrieve apps data + * Connects to laboite-webapp API to retrieve data + * Parse the json received and display datas on the LED matrix * Indoor temperature (optionnal, uncomment SENSORS to enable it) * Automatic screen brightness adjusting (optionnal, uncomment SENSORS to enable it) * Stop scrolling function (optionnal, uncomment SENSORS to enable it) @@ -22,41 +23,37 @@ * Coffees * Emails * RATP + * Agenda Circuit: - * Ethernet shield attached to pins 10, 11, 12, 13 - * or ESP8266 Wifi module (not stable yet) attached to pins 0 and 1 + * Ethernet shield attached to pins 10, 11, 12, 13 (Arduino Yún support from v3.4) * Sure Electronics 3216 LED matrix attached to pins 4, 5, 6, 7 - * TinkerKit LDR, Thermistor and Button modules on I0, I1, I2 (optionnal, uncomment SENSORS to enable it) + * LDR, Thermistor and Button modules on A0, A1, A2 (optionnal, uncomment SENSORS to enable it) created 15 Dec 2011 by Baptiste Gaultier and Tanguy Ropitault - modified 30 Dec 2014 + modified 31 Mar 2015 by Baptiste Gaultier This code is in the public domain. */ + // uncomment if you want to enable debug //#define DEBUG // uncomment if you want to enable Ethernet #define ETHERNET // uncomment if you want to enable dotmatrix #define HT1632C -// uncomment if you want to enable TinkerKit! sensors -//#define TINKERKIT // uncomment if you want to enable classic sensors //#define SENSORS // uncomment if you want to enable the AVR Watchdog -//#define WATCHDOG +#define WATCHDOG #ifdef ETHERNET #include #include #endif -#ifdef TINKERKIT -#include -#endif #ifdef HT1632C #include #endif @@ -68,12 +65,6 @@ // enter a MAC address and IP address for your controller below. byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0xE5, 0x91 }; -// fill in an available IP address on your network here, -// for auto-configuration: -IPAddress ip(192, 168, 2, 64); -IPAddress subnet(255, 255, 255, 0); -IPAddress gateway(192, 168, 2, 1); - // initialize the library instance: EthernetClient client; #endif @@ -85,42 +76,67 @@ char apikey[] = "964de680"; // your device API key String currentLine = ""; // string to hold the text from server -// variables used to display infos +// Modular Apps code +// (uncomment only the apps you need, otherwise the sketch will be too big) +#define ENERGY +#define MESSAGES +#define COFFEES +#define AGENDA + + +// Variables used to display infos + char hour[3]; char minutes[3]; -char bus[3]; -char bikes[3]; -char emails[3]; + byte todayIcon; +char temperature[3]; byte tomorrowIcon; +char low[3]; +char high[3]; byte color; + #ifdef SENSORS char indoorTemperatureString[3]; byte indoorTemperature; #endif -#ifdef TINKERKIT -char indoorTemperatureString[3]; -byte indoorTemperature; -#endif -char temperature[3]; -char low[3]; -char high[3]; + +char bus[3]; + +char bikes[3]; + +#ifdef ENERGY byte energy[7]; +#endif + +#ifdef EMAILS +char emails[3]; +#endif + +#ifdef MESSAGES char message[140]; +#endif + +#ifdef COFFEES +char coffees[3]; +#endif + char eventStart[5]; char eventSummary[64]; -// parser variables +// Parser variables boolean readingTime = false; -boolean readingBus = false; -boolean readingBikes = false; -boolean readingEmails = false; -boolean readingCoffees = false; + boolean readingTodayIcon = false; boolean readingTemperature = false; boolean readingTomorrowIcon = false; boolean readingLow = false; boolean readingHigh = false; + +boolean readingBus = false; +boolean readingBikes = false; + +#ifdef ENERGY boolean readingDay0 = false; boolean readingDay1 = false; boolean readingDay2 = false; @@ -128,31 +144,48 @@ boolean readingDay3 = false; boolean readingDay4 = false; boolean readingDay5 = false; boolean readingDay6 = false; +#endif + boolean readingMessage = false; + +#ifdef COFFEES +boolean readingCoffees = false; +#endif + +boolean readingEmails = false; + boolean readingEventStart = false; boolean readingEventSummary = false; -// apps variables + +// Apps variables + boolean timeEnabled = false; boolean busEnabled = false; boolean bikesEnabled = false; boolean emailsEnabled = false; boolean weatherEnabled = false; +#ifdef ENERGY boolean energyEnabled = false; +#endif boolean messagesEnabled = false; - -#ifdef TINKERKIT -TKLightSensor ldr(I0); // ldr used to adjust dotmatrix brightness -TKThermistor therm(I1); // thermistor used for indoor temperature -TKButton button(I2); // pushbutton used to start/stop scrolling +#ifdef COFFEES +boolean coffeesEnabled = false; +#endif +#ifdef AGENDA +boolean agendaEnabled = false; #endif #ifdef SENSORS -// constants won't change. They're used here to +// Sensors constants won't change. They're used here to // set pin numbers: const byte ldrPin = A0; // ldr used to adjust dotmatrix brightness const byte thermistorPin = A1; // thermistor used for indoor temperature const byte buttonPin = A2; // pushbutton used to start/stop scrolling + +// Sensors variables +int brightnessValue = 0; // value read from the LDR +int previousBrightnessValue = 512; // previous value of brightness #endif #ifdef HT1632C @@ -176,9 +209,14 @@ uint16_t busSprite[9] = { 0x00fc, 0x0186, 0x01fe, 0x0102, 0x0102, 0x01fe, 0x017a uint16_t bikeSprite[9] = { 0x020c, 0x0102, 0x008c, 0x00f8, 0x078e, 0x0ab9, 0x0bd5, 0x0891, 0x070e}; // emails app sprite: uint16_t emailSprite[6] = { 0x00fe, 0x0145, 0x0129, 0x0111, 0x0101, 0x00fe}; - -int brightnessValue = 0; // value read from the LDR -int previousBrightnessValue = 512; // previous value of brightness +#ifdef COFFEES +// coffees app sprite +uint16_t coffeeSprite[8] = {0x4800, 0x2400, 0x4800, 0xff00, 0x8500, 0x8600, 0x8400, 0x7800}; +#endif +#ifdef AGENDA +// agenda app sprite +uint16_t calendarSprite[8] = { 0b01111111, 0b01111111, 0b01000001, 0b01001001, 0b01001001, 0b01001001, 0b01000001, 0b01111111 }; +#endif boolean scrolling = true; // value modified when button is pressed @@ -196,18 +234,12 @@ void setup() { // display a welcome message: #ifdef DEBUG - Serial.println("laboite v3.2.2 starting..."); + Serial.println("laboite v3.4 starting..."); #endif // attempt a DHCP connection: #ifdef ETHERNET - if (!Ethernet.begin(mac)) { - // if DHCP fails, start with a hard-coded address: - #ifdef DEBUG - Serial.println("failed to get an IP address using DHCP, trying manually"); - #endif - Ethernet.begin(mac, ip, subnet); - } + Ethernet.begin(mac); #endif #ifdef DEBUG @@ -242,7 +274,6 @@ void setup() { } - void loop() { if (client.connected()) { @@ -266,7 +297,7 @@ void loop() #endif - for (int x = 32; x > -130; x--) { + for (int x = 32; x > -162; x--) { adjustBrightness(); // scroll through apps @@ -274,12 +305,25 @@ void loop() scrollSecondPanel(x); scrollThirdPanel(x); scrollFourthPanel(x); + #ifdef AGENDA + if(agendaEnabled) + scrollFifthPanel(x); + else { + if(x == -129) { + dotmatrix.sendframe(); + break; + } + } dotmatrix.sendframe(); delay(30); + } + #endif + #ifdef MESSAGES scrollSixthPanel(); + #endif #ifdef TINKERKIT if(button.read()) @@ -307,10 +351,6 @@ void loop() #endif delay(requestInterval/4); } - #ifdef TINKERKIT - if(button.read()) - scrolling = !scrolling; - #endif #ifdef SENSORS if (digitalRead(buttonPin) == HIGH) scrolling = !scrolling; diff --git a/laboiteLib.ino b/laboiteLib.ino index 9b3b753..afe3481 100644 --- a/laboiteLib.ino +++ b/laboiteLib.ino @@ -57,7 +57,7 @@ boolean parseJSON() { if (readingTime) { if (inChar != ',' && inChar != '}') { if (inChar != '"' && inChar != ':') - content += inChar; + content += inChar; } else { readingTime = false; @@ -132,6 +132,35 @@ boolean parseJSON() { } } + #ifdef COFFEES + // fetch Coffees app data + if (currentLine.endsWith("\"coffees\":")) { + readingCoffees = true; + content = ""; + } + + if (readingCoffees) { + if (inChar != ',' && inChar != '}') { + if (inChar != '"' && inChar != ':') + content += inChar; + } + else { + readingCoffees = false; + coffees[0] = content.charAt(0); + coffees[1] = content.charAt(1); + coffees[2] = '\0'; + + coffeesEnabled = true; + + #ifdef DEBUG + Serial.print("Coffees: "); + Serial.println(coffees); + #endif + } + } + #endif + + #ifdef EMAILS // fetch Emails app data if (currentLine.endsWith("\"emails\":")) { readingEmails = true; @@ -157,8 +186,10 @@ boolean parseJSON() { #endif } } + #endif // fetch Energy app data + #ifdef ENERGY if (currentLine.endsWith("\"day0\":")) { readingDay0 = true; content = ""; @@ -167,7 +198,7 @@ boolean parseJSON() { if (readingDay0) { if (inChar != ',' && inChar != '}') { if (inChar != '"' && inChar != ':') - content += inChar; + content += inChar; } else { readingDay0 = false; @@ -282,7 +313,65 @@ boolean parseJSON() { #endif } } + #endif + + #ifdef AGENDA. + // fetch Agenda app data + if (currentLine.endsWith("\"dtstart\":")) { + readingEventStart = true; + content = ""; + } + + if (readingEventStart) { + if (inChar != ',' && inChar != '}') { + if (inChar != '"' && inChar != ':') + content += inChar; + } + else { + readingEventStart = false; + content.toCharArray(eventStart, 5); + eventStart[4] = '\0'; + + agendaEnabled = true; + + #ifdef DEBUG + Serial.print("Event : "); + Serial.print(eventStart[0]); + Serial.print(eventStart[1]); + Serial.print(":"); + Serial.print(eventStart[2]); + Serial.print(eventStart[3]); + Serial.print(", "); + #endif + } + } + if (currentLine.endsWith("\"summary\":")) { + readingEventSummary = true; + content = ""; + } + + if (readingEventSummary) { + if (inChar != ',' && inChar != '}') { + if (inChar != '"' && inChar != ':') + content += inChar; + } + else { + readingEventSummary = false; + content.toCharArray(eventSummary, min(content.length() + 1, 64)); + eventSummary[64] = '\0'; + + agendaEnabled = true; + + #ifdef DEBUG + Serial.println(eventSummary); + #endif + } + } + #endif + + #ifdef MESSAGES + // fetch Messages app data if (currentLine.endsWith("\"messages\":")) { readingMessage = true; content = ""; @@ -306,6 +395,7 @@ boolean parseJSON() { #endif } } + #endif // fetch Weather app data if (currentLine.endsWith("y\":{\"icon\":")) { @@ -413,12 +503,22 @@ boolean parseJSON() { void resetApps() { timeEnabled = false; + weatherEnabled = false; busEnabled = false; bikesEnabled = false; - emailsEnabled = false; - weatherEnabled = false; + #ifdef ENERGY energyEnabled = false; + #endif messagesEnabled = false; + #ifdef COFFEES + coffeesEnabled = false; + #endif + #ifdef EMAILS + emailsEnabled = false; + #endif + #ifdef AGENDA + agendaEnabled = false; + #endif } int stringToInt(String string) { @@ -444,17 +544,6 @@ void adjustBrightness() { #endif // read the analog in value: - #ifdef TINKERKIT - brightnessValue = (ldr.read() + previousBrightnessValue) / 2; - pwm = map(brightnessValue, 0, 1023, 0, 15); - dotmatrix.pwm(pwm); - previousBrightnessValue = brightnessValue; - - // check if scrolling button has been pressed - if(button.read()) - scrolling = !scrolling; - #endif - #ifdef SENSORS brightnessValue = (analogRead(ldrPin) + previousBrightnessValue) / 2; pwm = (brightnessValue*15)/1023; @@ -497,13 +586,11 @@ void scrollFirstPanel(int x) { } if(x == 0) { - #ifdef SENSOR - #ifdef TINKERKIT + #ifdef SENSORS waitAWhile(); printTemperature(x+17, indoorTemperatureString[0], indoorTemperatureString[1], ORANGE); dotmatrix.sendframe(); #endif - #endif dotmatrix.sendframe(); waitAWhile(); } @@ -522,7 +609,7 @@ void scrollSecondPanel(int x) { } if(x >= -32 && x < 0) { - #ifdef SENSOR + #ifdef SENSORS printTemperature(x+17, indoorTemperatureString[0], indoorTemperatureString[1], ORANGE); #else printTemperature(x+17, temperature[0], temperature[1], RED); @@ -588,22 +675,36 @@ void scrollFourthPanel(int x) { } if(x <= -63) { + #ifdef EMAILS // emails app if(emailsEnabled) { if(emails[1] != '\0') dotmatrix.putchar(x+116, 1, emails[1], GREEN); dotmatrix.putbitmap(x+100, 1, emailSprite, 9, 6, ORANGE); - //dotmatrix.putchar(x+97, 7, ' ', GREEN); dotmatrix.putchar(x+109, 1, ' ', GREEN); dotmatrix.putchar(x+111, 1, emails[0], GREEN); } + #endif + + #ifdef COFFEES + // coffees app + if(coffeesEnabled) { + if(coffees[1] != '\0') + dotmatrix.putchar(x+116, 2, coffees[1], GREEN); + dotmatrix.putbitmap(x+99, 0, coffeeSprite, 16, 8, ORANGE); + dotmatrix.putchar(x+108, 2, ' ', GREEN); + dotmatrix.putchar(x+111, 2, coffees[0], GREEN); + } + #endif // energy app + #ifdef ENERGY if(energyEnabled) { for(int i = 0; i < 7; i++) { drawChart(x + 97 + (i*4), energy[i]); } } + #endif if(x == -65 || x == -95) { waitAWhile(); @@ -615,12 +716,42 @@ void scrollFourthPanel(int x) { } } +void scrollFifthPanel(int x) { + //fourth panel : coffees and energy -64→-96 + if(x <= -63) { + // agenda app + if(agendaEnabled) { + dotmatrix.putchar(x+133, 0, ' ', ORANGE); + dotmatrix.putchar(x+138, 0, ' ', ORANGE); + dotmatrix.putchar(x+142, 0, ' ', ORANGE); + dotmatrix.putchar(x+147, 0, ' ', ORANGE); + dotmatrix.putchar(x+152, 0, ' ', ORANGE); + dotmatrix.putchar(x+157, 0, ' ', ORANGE); + dotmatrix.putchar(x+133, 1, ' ', ORANGE); + dotmatrix.putbitmap(x+129, 0, calendarSprite,8,8, RED); + dotmatrix.putchar(x+138, 1, eventStart[0], ORANGE); + dotmatrix.putchar(x+143, 1, eventStart[1], ORANGE); + dotmatrix.putchar(x+147, 1, ':', ORANGE); + dotmatrix.putchar(x+151, 1, eventStart[2], ORANGE); + dotmatrix.putchar(x+156, 1, eventStart[3], ORANGE); + + if(x == -129) + dotmatrix.hscrolltext(9, eventSummary, ORANGE, 10, 1, LEFT); + if(timeEnabled) + printTime(x+161); + } + } +} + +#ifdef MESSAGES void scrollSixthPanel() { // fifth panel : message if(messagesEnabled) dotmatrix.hscrolltext(9, message, GREEN, 10, 1, LEFT); } - +#endif + +#ifdef ENERGY void drawChart(byte x, byte height) { dotmatrix.rect(x, 16-height, x+2, 15, GREEN); if(height > 2) @@ -628,6 +759,7 @@ void drawChart(byte x, byte height) { dotmatrix.line(x+3, 16-height, x+3, 15, BLACK); } #endif +#endif #ifdef SENSORS int getTemperature() {