#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
#define OLED_RESET 30
Adafruit_SSD1306 display(OLED_RESET);
#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2
#define DISPLAY_CHAR_SIZE 6
#define TEMP_OFFSET_Y 22
#define ICON_RAIN 0
#define ICON_SNOW 1
#define ICON_CLOUD 2
#define ICON_CLOUD_SUN 3
#define ICON_SUN 4
#define ICON_LOAD 5
#define ICON_ERROR 6
#define ICON_NBR ICON_ERROR + 1
#define IMAGE_OFFSET_X 72
#define IMAGE_OFFSET_Y 8
#define IMAGE_HEIGHT 55
#define IMAGE_WIDTH 55
static const unsigned char PROGMEM images[][385] =
{
// rain
{ 0x0,0x0,0x7f,0x0,0x0,0x0,0x0,
0x0,0x3,0xff,0xc0,0x60,0x0,0x0,
0x0,0x7,0xff,0xf3,0xfc,0x0,0x0,
0x0,0x1f,0xff,0xff,0xff,0x0,0x0,
0x0,0x3f,0xff,0xff,0xff,0x0,0x0,
0x0,0x7f,0xff,0xff,0xff,0xf8,0x0,
0x0,0x7f,0xff,0xff,0xff,0xfe,0x0,
0x0,0xff,0xff,0xff,0xff,0xff,0x0,
0x0,0xff,0xff,0xff,0xff,0xff,0x0,
0x0,0xff,0xff,0xff,0xff,0xff,0x0,
0x0,0xff,0xff,0xff,0xff,0xff,0x0,
0x1,0xff,0xff,0xff,0xff,0xff,0x0,
0x1,0xff,0xff,0xff,0xff,0xff,0x0,
0x7,0xff,0xff,0xff,0xff,0xff,0xc0,
0xf,0xff,0xff,0xff,0xff,0xff,0xe0,
0xf,0xff,0xff,0xff,0xff,0xff,0xe0,
0x1f,0xff,0xff,0xff,0xff,0xff,0xf0,
0x1f,0xff,0xff,0xff,0xff,0xff,0xf0,
0x1f,0xff,0xff,0xff,0xff,0xff,0xf0,
0x1f,0xff,0xff,0xff,0xff,0xff,0xf0,
0x1f,0xff,0xff,0xff,0xff,0xff,0xf0,
0x1f,0xff,0xff,0xff,0xff,0xff,0xf0,
0x1f,0xff,0xff,0xff,0xff,0xff,0xf0,
0xf,0xff,0xff,0xff,0xff,0xff,0xe0,
0x7,0xff,0xff,0xff,0xff,0xff,0xc0,
0x3,0xff,0xff,0xff,0xff,0xff,0x80,
0x0,0xff,0xff,0xff,0xff,0xfe,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x10,0x0,
0x0,0x3,0x0,0x8,0x0,0x30,0x0,
0x0,0x7,0x0,0x38,0x0,0x70,0x0,
0x0,0xf,0x0,0x78,0x1,0xf0,0x0,
0x0,0x1f,0x0,0xf8,0x3,0xf0,0x0,
0x0,0x3f,0x1,0xf8,0x7,0xe0,0x0,
0x0,0x7f,0x3,0xf8,0xf,0xe0,0x0,
0x0,0x7f,0x3,0xf8,0xf,0xe0,0x0,
0x0,0xfe,0x3,0xf8,0xf,0xe0,0x0,
0x0,0x7e,0x3,0xf0,0xf,0xe0,0x0,
0x0,0x7e,0x1,0xf0,0x7,0xc0,0x0,
0x0,0x18,0x0,0xc0,0x1,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x20,0x1,0x80,0x0,0x0,
0x0,0x0,0xe0,0x3,0x80,0x0,0x0,
0x0,0x1,0xe0,0xf,0x80,0x0,0x0,
0x0,0x3,0xe0,0x1f,0x0,0x0,0x0,
0x0,0x7,0xe0,0x3f,0x0,0x0,0x0,
0x0,0xf,0xe0,0x7f,0x0,0x0,0x0,
0x0,0xf,0xe0,0x7f,0x0,0x0,0x0,
0x0,0x1f,0xe0,0x7f,0x0,0x0,0x0,
0x0,0xf,0xc0,0x7f,0x0,0x0,0x0,
0x0,0xf,0xc0,0x3e,0x0,0x0,0x0,
0x0,0x7,0x80,0x1c,0x0,0x0,0x0 },
// snow
{ 0x0,0x0,0x0,0x30,0x0,0x0,0x0,
0x0,0x0,0x0,0x38,0x0,0x0,0x0,
0x0,0x0,0x1c,0x38,0x70,0x0,0x0,
0x0,0x0,0x1e,0x38,0xf0,0x0,0x0,
0x0,0x3,0x1f,0x39,0xe3,0x80,0x0,
0x0,0x3,0x8f,0xbf,0xc3,0x80,0x0,
0x0,0x3,0x87,0xff,0xc3,0x80,0x0,
0x0,0x3,0x83,0xff,0x83,0x80,0x0,
0x0,0xc3,0x81,0xff,0x3,0x8e,0x0,
0x1,0xf3,0x80,0xfe,0x3,0x9e,0x0,
0x0,0xfb,0x80,0x78,0x3,0xbc,0x0,
0x0,0x7f,0x80,0x38,0x3,0xfc,0x0,
0x0,0x3f,0x80,0x38,0x3,0xf8,0x0,
0x0,0x1f,0x80,0x38,0x3,0xf0,0x0,
0xf,0xff,0x80,0x38,0x3,0xff,0xe0,
0xf,0xff,0xc0,0x38,0x7,0xff,0xe0,
0xf,0xff,0xe0,0x38,0xf,0xff,0xc0,
0x0,0x1,0xf0,0x38,0x1f,0x0,0x0,
0x0,0x0,0xf8,0x38,0x3e,0x0,0x0,
0x30,0x0,0x7c,0x38,0x7c,0x0,0x38,
0x38,0x0,0x3e,0x38,0xf8,0x0,0x78,
0x3e,0x0,0x1f,0x39,0xf0,0x0,0xf8,
0x1f,0x0,0xf,0xbb,0xe0,0x1,0xf0,
0xf,0x80,0x7,0xff,0xc0,0x3,0xe0,
0x7,0xc0,0x3,0xff,0x80,0x7,0xc0,
0x7,0xc0,0x1,0xff,0x0,0xf,0x80,
0x7f,0xff,0xff,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xff,0xff,0xfc,
0x3,0xe0,0x1,0xff,0x0,0x7,0xc0,
0x7,0xc0,0x3,0xff,0x80,0x7,0xc0,
0xf,0x80,0x7,0xff,0xc0,0x3,0xe0,
0x1f,0x0,0xf,0xbb,0xe0,0x1,0xf0,
0x3e,0x0,0x1f,0x39,0xf0,0x0,0xf8,
0x3c,0x0,0x3e,0x38,0xf8,0x0,0x38,
0x38,0x0,0x7c,0x38,0x7c,0x0,0x18,
0x0,0x0,0xf8,0x38,0x3e,0x0,0x0,
0x0,0x1,0xf0,0x38,0x1f,0x0,0x0,
0x7,0xff,0xe0,0x38,0xf,0xff,0xe0,
0xf,0xff,0xc0,0x38,0x7,0xff,0xe0,
0xf,0xff,0x80,0x38,0x3,0xff,0xe0,
0x0,0x1f,0x80,0x38,0x3,0xf0,0x0,
0x0,0x3f,0x80,0x38,0x3,0xf8,0x0,
0x0,0x7f,0x80,0x38,0x3,0xfc,0x0,
0x0,0x7b,0x80,0x3c,0x3,0xbe,0x0,
0x0,0xf3,0x80,0xfe,0x3,0x9e,0x0,
0x0,0xe3,0x81,0xff,0x3,0x86,0x0,
0x0,0x43,0x83,0xff,0x83,0x80,0x0,
0x0,0x3,0x87,0xff,0xc3,0x80,0x0,
0x0,0x3,0x87,0xfb,0xe3,0x80,0x0,
0x0,0x3,0x8f,0x39,0xf1,0x80,0x0,
0x0,0x0,0x1e,0x38,0xf0,0x0,0x0,
0x0,0x0,0x1c,0x38,0x70,0x0,0x0,
0x0,0x0,0x0,0x38,0x0,0x0,0x0,
0x0,0x0,0x0,0x18,0x0,0x0,0x0 } ,
// cloud
{ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x3f,0xf0,0x0,0x0,0x0,
0x0,0x0,0xff,0xfc,0x0,0x0,0x0,
0x0,0x3,0xff,0xff,0x0,0x0,0x0,
0x0,0x7,0xff,0xff,0x80,0x0,0x0,
0x0,0xf,0xff,0xff,0xc0,0x0,0x0,
0x0,0x1f,0xff,0xff,0xe0,0x0,0x0,
0x0,0x3f,0xff,0xff,0xf7,0x0,0x0,
0x0,0x7f,0xff,0xff,0xff,0xe0,0x0,
0x0,0x7f,0xff,0xff,0xff,0xf0,0x0,
0x0,0xff,0xff,0xff,0xff,0xf8,0x0,
0x0,0xff,0xff,0xff,0xff,0xfc,0x0,
0x0,0xff,0xff,0xff,0xff,0xfc,0x0,
0x0,0xff,0xff,0xff,0xff,0xfe,0x0,
0x1,0xff,0xff,0xff,0xff,0xfe,0x0,
0x1,0xff,0xff,0xff,0xff,0xfe,0x0,
0x1,0xff,0xff,0xff,0xff,0xfe,0x0,
0x1,0xff,0xff,0xff,0xff,0xff,0x0,
0x7,0xff,0xff,0xff,0xff,0xff,0xc0,
0x1f,0xff,0xff,0xff,0xff,0xff,0xf0,
0x3f,0xff,0xff,0xff,0xff,0xff,0xf8,
0x3f,0xff,0xff,0xff,0xff,0xff,0xf8,
0x7f,0xff,0xff,0xff,0xff,0xff,0xfc,
0x7f,0xff,0xff,0xff,0xff,0xff,0xfc,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
0x7f,0xff,0xff,0xff,0xff,0xff,0xfc,
0x7f,0xff,0xff,0xff,0xff,0xff,0xfc,
0x3f,0xff,0xff,0xff,0xff,0xff,0xf8,
0x1f,0xff,0xff,0xff,0xff,0xff,0xf0,
0xf,0xff,0xff,0xff,0xff,0xff,0xe0,
0x3,0xff,0xff,0xff,0xff,0xff,0x80,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0 },
// cloud and sun
{ 0x0,0x0,0x7,0x0,0x0,0x0,0x0,
0x0,0x0,0xf,0x80,0x0,0x0,0x0,
0x0,0x0,0x1f,0xc0,0x0,0x0,0x0,
0x0,0x0,0x1f,0xc0,0x0,0x0,0x0,
0x0,0x0,0x1f,0xc0,0x0,0x0,0x0,
0x0,0x40,0x1f,0xc0,0x10,0x0,0x0,
0x1,0xf0,0x1f,0xc0,0x7c,0x0,0x0,
0x3,0xf8,0xf,0xc0,0xfe,0x0,0x0,
0x3,0xfc,0x0,0x1,0xfe,0x0,0x0,
0x3,0xfc,0x0,0x3,0xfe,0x0,0x0,
0x1,0xfc,0xf,0x81,0xfc,0x0,0x0,
0x0,0xf0,0x7f,0xf0,0x78,0x0,0x0,
0x0,0x60,0xff,0xf8,0x70,0x0,0x0,
0x0,0x63,0xff,0xfe,0x20,0x0,0x0,
0x0,0x3,0xff,0xfe,0x0,0x0,0x0,
0x0,0x7,0xff,0xff,0x0,0x0,0x0,
0x0,0xf,0xff,0xff,0x80,0x0,0x0,
0x0,0xf,0xff,0xff,0x80,0x0,0x0,
0xe,0x1f,0xff,0xff,0xc7,0x0,0x0,
0x3f,0x1f,0xff,0xff,0xc7,0xe0,0x0,
0x7f,0x1f,0xff,0xff,0x1,0xf0,0x0,
0x7f,0x1f,0xff,0xfc,0x0,0x70,0x0,
0x7f,0x1f,0x80,0x70,0x0,0x30,0x0,
0x7f,0x1c,0x0,0x0,0x38,0x0,0x0,
0x3f,0x10,0x0,0x1,0xfe,0x0,0x0,
0x0,0x0,0x0,0x3,0xff,0x0,0x0,
0x0,0x0,0xff,0xc7,0xff,0x80,0x0,
0x0,0x3,0xff,0xff,0xff,0xc0,0x0,
0x0,0x7,0xff,0xff,0xff,0xc1,0x0,
0x0,0xf,0xff,0xff,0xff,0xdf,0xe0,
0x0,0x1f,0xff,0xff,0xff,0xff,0xf0,
0x0,0x3f,0xff,0xff,0xff,0xff,0xf8,
0x0,0x7f,0xff,0xff,0xff,0xff,0xfc,
0x0,0x7f,0xff,0xff,0xff,0xff,0xfc,
0x0,0x7f,0xff,0xff,0xff,0xff,0xfc,
0x0,0xff,0xff,0xff,0xff,0xff,0xfe,
0x0,0xff,0xff,0xff,0xff,0xff,0xfe,
0x0,0xff,0xff,0xff,0xff,0xff,0xfc,
0x0,0xff,0xff,0xff,0xff,0xff,0xfc,
0x7,0xff,0xff,0xff,0xff,0xff,0xfc,
0x1f,0xff,0xff,0xff,0xff,0xff,0xf8,
0x1f,0xff,0xff,0xff,0xff,0xff,0xf0,
0x3f,0xff,0xff,0xff,0xff,0xff,0xc0,
0x7f,0xff,0xff,0xff,0xff,0xff,0x80,
0x7f,0xff,0xff,0xff,0xff,0xff,0x80,
0x7f,0xff,0xff,0xff,0xff,0xff,0x80,
0xff,0xff,0xff,0xff,0xff,0xff,0x80,
0x7f,0xff,0xff,0xfc,0xff,0xff,0x0,
0x7f,0xff,0xff,0xf8,0xff,0xfe,0x0,
0x7f,0xff,0xff,0xf0,0x7f,0xfe,0x0,
0x7f,0xff,0xff,0xc0,0x3f,0xfc,0x0,
0x3f,0xff,0x0,0x0,0xf,0xf0,0x0,
0x1f,0xfe,0x0,0x0,0x0,0x0,0x0,
0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x3,0xe0,0x0,0x0,0x0,0x0,0x0 },
// sun
{ 0x0,0x0,0x0,0x38,0x0,0x0,0x0,
0x0,0x0,0x0,0x7c,0x0,0x0,0x0,
0x0,0x0,0x0,0x7c,0x0,0x0,0x0,
0x0,0x0,0x0,0x7c,0x0,0x0,0x0,
0x0,0x0,0x0,0x7c,0x0,0x0,0x0,
0x0,0x0,0x0,0x7c,0x0,0x0,0x0,
0x0,0x0,0x0,0x7c,0x0,0x0,0x0,
0x0,0x60,0x0,0x7c,0x0,0xc,0x0,
0x0,0xf0,0x0,0x7c,0x0,0x1e,0x0,
0x1,0xf8,0x0,0x10,0x0,0x3f,0x0,
0x1,0xfc,0x0,0x0,0x0,0x7f,0x0,
0x0,0xfe,0x0,0x0,0x0,0xfe,0x0,
0x0,0x7f,0x0,0x0,0x1,0xfc,0x0,
0x0,0x3f,0x0,0x0,0x1,0xf8,0x0,
0x0,0x1e,0x1,0xff,0x0,0xf0,0x0,
0x0,0xc,0x7,0xff,0xc0,0x60,0x0,
0x0,0x0,0x1f,0xff,0xf0,0x0,0x0,
0x0,0x0,0x3f,0xff,0xf8,0x0,0x0,
0x0,0x0,0x7f,0xff,0xfc,0x0,0x0,
0x0,0x0,0xff,0xff,0xfe,0x0,0x0,
0x0,0x0,0xff,0xff,0xfe,0x0,0x0,
0x0,0x1,0xff,0xff,0xff,0x0,0x0,
0x0,0x1,0xff,0xff,0xff,0x0,0x0,
0x0,0x3,0xff,0xff,0xff,0x80,0x0,
0x0,0x3,0xff,0xff,0xff,0x80,0x0,
0x7f,0x83,0xff,0xff,0xff,0x83,0xfc,
0xff,0x83,0xff,0xff,0xff,0x83,0xfe,
0xff,0xc3,0xff,0xff,0xff,0x87,0xfe,
0xff,0x83,0xff,0xff,0xff,0x83,0xfe,
0x7f,0x83,0xff,0xff,0xff,0x83,0xfc,
0x0,0x3,0xff,0xff,0xff,0x80,0x0,
0x0,0x3,0xff,0xff,0xff,0x80,0x0,
0x0,0x1,0xff,0xff,0xff,0x0,0x0,
0x0,0x1,0xff,0xff,0xff,0x0,0x0,
0x0,0x0,0xff,0xff,0xfe,0x0,0x0,
0x0,0x0,0xff,0xff,0xfe,0x0,0x0,
0x0,0x0,0x7f,0xff,0xfc,0x0,0x0,
0x0,0x0,0x3f,0xff,0xf8,0x0,0x0,
0x0,0x0,0x1f,0xff,0xf0,0x0,0x0,
0x0,0xc,0x7,0xff,0xc0,0x60,0x0,
0x0,0x1e,0x1,0xff,0x0,0xf0,0x0,
0x0,0x3f,0x0,0x0,0x1,0xf8,0x0,
0x0,0x7f,0x0,0x0,0x1,0xfc,0x0,
0x0,0xfe,0x0,0x0,0x0,0xfe,0x0,
0x1,0xfc,0x0,0x0,0x0,0x7f,0x0,
0x1,0xf8,0x0,0x10,0x0,0x3f,0x0,
0x0,0xf0,0x0,0x7c,0x0,0x1e,0x0,
0x0,0x60,0x0,0x7c,0x0,0xc,0x0,
0x0,0x0,0x0,0x7c,0x0,0x0,0x0,
0x0,0x0,0x0,0x7c,0x0,0x0,0x0,
0x0,0x0,0x0,0x7c,0x0,0x0,0x0,
0x0,0x0,0x0,0x7c,0x0,0x0,0x0,
0x0,0x0,0x0,0x7c,0x0,0x0,0x0,
0x0,0x0,0x0,0x7c,0x0,0x0,0x0,
0x0,0x0,0x0,0x38,0x0,0x0,0x0 },
// load
{ 0x0,0x0,0x0,0x0,0x0,0x0,0x30,
0x0,0x0,0x7,0xff,0xc0,0x0,0xf0,
0x0,0x0,0x3f,0xff,0xfc,0x1,0xf8,
0x0,0x1,0xff,0xff,0xff,0x3,0xf8,
0x0,0x3,0xff,0xff,0xff,0xc7,0xf8,
0x0,0xf,0xff,0xff,0xff,0xef,0xf8,
0x0,0x1f,0xff,0xff,0xff,0xff,0xf8,
0x0,0x3f,0xff,0xff,0xff,0xff,0xf8,
0x0,0x7f,0xff,0xff,0xff,0xff,0xf8,
0x0,0xff,0xff,0xff,0xff,0xff,0xf8,
0x1,0xff,0xfc,0x0,0x7f,0xff,0xf8,
0x3,0xff,0xf0,0x0,0xf,0xff,0xf8,
0x7,0xff,0xc0,0x0,0x7,0xff,0xf8,
0x7,0xff,0x80,0x0,0xf,0xff,0xf8,
0xf,0xff,0x0,0x0,0x1f,0xff,0xf8,
0x1f,0xfe,0x0,0x0,0x3f,0xff,0xf8,
0x1f,0xfc,0x0,0x0,0x7f,0xff,0xf8,
0x1f,0xf8,0x0,0x0,0xff,0xff,0xf8,
0x3f,0xf0,0x0,0x0,0xff,0xff,0xf8,
0x3f,0xf0,0x0,0x0,0xff,0xff,0xf8,
0x3f,0xe0,0x0,0x0,0xff,0xff,0xf0,
0x7f,0xe0,0x0,0x0,0x0,0x0,0x0,
0x7f,0xc0,0x0,0x0,0x0,0x0,0x0,
0x7f,0xc0,0x0,0x0,0x0,0x0,0x0,
0x7f,0xc0,0x0,0x0,0x0,0x0,0x0,
0x7f,0xc0,0x0,0x0,0x0,0x0,0x0,
0x7f,0xc0,0x0,0x0,0x0,0x7,0xfc,
0x7f,0xc0,0x0,0x0,0x0,0x7,0xfc,
0x7f,0xc0,0x0,0x0,0x0,0x7,0xfc,
0x0,0x0,0x0,0x0,0x0,0x7,0xfc,
0x0,0x0,0x0,0x0,0x0,0x7,0xfc,
0x0,0x0,0x0,0x0,0x0,0x7,0xfc,
0x0,0x0,0x0,0x0,0x0,0x7,0xfc,
0x0,0x0,0x0,0x0,0x0,0xf,0xfc,
0x1f,0xff,0xfe,0x0,0x0,0xf,0xf8,
0x3f,0xff,0xfe,0x0,0x0,0x1f,0xf8,
0x3f,0xff,0xfe,0x0,0x0,0x1f,0xf8,
0x3f,0xff,0xfe,0x0,0x0,0x3f,0xf0,
0x3f,0xff,0xfc,0x0,0x0,0x7f,0xf0,
0x3f,0xff,0xf8,0x0,0x0,0xff,0xf0,
0x3f,0xff,0xf0,0x0,0x1,0xff,0xe0,
0x3f,0xff,0xe0,0x0,0x3,0xff,0xc0,
0x3f,0xff,0xc0,0x0,0x7,0xff,0xc0,
0x3f,0xff,0xe0,0x0,0x1f,0xff,0x80,
0x3f,0xff,0xfc,0x0,0x7f,0xff,0x0,
0x3f,0xff,0xff,0xff,0xff,0xfe,0x0,
0x3f,0xff,0xff,0xff,0xff,0xfc,0x0,
0x3f,0xff,0xff,0xff,0xff,0xf8,0x0,
0x3f,0xff,0xff,0xff,0xff,0xf0,0x0,
0x3f,0xef,0xff,0xff,0xff,0xe0,0x0,
0x3f,0xc7,0xff,0xff,0xff,0x80,0x0,
0x3f,0x81,0xff,0xff,0xff,0x0,0x0,
0x3f,0x0,0x7f,0xff,0xf8,0x0,0x0,
0x1e,0x0,0x7,0xff,0xc0,0x0,0x0,
0x18,0x0,0x0,0x0,0x0,0x0,0x0 },
// error
{ 0x0,0x20,0x0,0x0,0x0,0x8,0x0,
0x0,0x38,0x0,0x0,0x0,0x38,0x0,
0x0,0x7c,0x0,0x0,0x0,0x7c,0x0,
0x0,0xfe,0x0,0x0,0x0,0xfe,0x0,
0x1,0xff,0x0,0x0,0x1,0xff,0x0,
0x7,0xff,0x80,0x0,0x3,0xff,0xc0,
0x7,0xff,0x80,0x0,0x3,0xff,0xc0,
0xf,0xff,0xe0,0x0,0xf,0xff,0xe0,
0x1f,0xff,0xf0,0x0,0x1f,0xff,0xf0,
0x3f,0xff,0xf8,0x0,0x3f,0xff,0xf8,
0xff,0xff,0xfc,0x0,0x7f,0xff,0xfe,
0x7f,0xff,0xfe,0x0,0xff,0xff,0xfc,
0x7f,0xff,0xfe,0x0,0xff,0xff,0xfc,
0x3f,0xff,0xff,0x1,0xff,0xff,0xf8,
0x1f,0xff,0xff,0xc7,0xff,0xff,0xf0,
0xf,0xff,0xff,0xef,0xff,0xff,0xe0,
0x7,0xff,0xff,0xff,0xff,0xff,0xc0,
0x1,0xff,0xff,0xff,0xff,0xff,0x0,
0x1,0xff,0xff,0xff,0xff,0xff,0x0,
0x0,0xff,0xff,0xff,0xff,0xfe,0x0,
0x0,0x7f,0xff,0xff,0xff,0xfc,0x0,
0x0,0x3f,0xff,0xff,0xff,0xf8,0x0,
0x0,0x1f,0xff,0xff,0xff,0xf0,0x0,
0x0,0x7,0xff,0xff,0xff,0xc0,0x0,
0x0,0x3,0xff,0xff,0xff,0x80,0x0,
0x0,0x3,0xff,0xff,0xff,0x80,0x0,
0x0,0x1,0xff,0xff,0xff,0x0,0x0,
0x0,0x0,0xff,0xff,0xfe,0x0,0x0,
0x0,0x1,0xff,0xff,0xff,0x0,0x0,
0x0,0x3,0xff,0xff,0xff,0x80,0x0,
0x0,0x3,0xff,0xff,0xff,0x80,0x0,
0x0,0x7,0xff,0xff,0xff,0xc0,0x0,
0x0,0x1f,0xff,0xff,0xff,0xf0,0x0,
0x0,0x3f,0xff,0xff,0xff,0xf8,0x0,
0x0,0x7f,0xff,0xff,0xff,0xfc,0x0,
0x0,0xff,0xff,0xff,0xff,0xfe,0x0,
0x1,0xff,0xff,0xff,0xff,0xff,0x0,
0x1,0xff,0xff,0xff,0xff,0xff,0x0,
0x7,0xff,0xff,0xff,0xff,0xff,0xc0,
0xf,0xff,0xff,0xef,0xff,0xff,0xe0,
0x1f,0xff,0xff,0xc7,0xff,0xff,0xf0,
0x3f,0xff,0xff,0x1,0xff,0xff,0xf8,
0x7f,0xff,0xfe,0x0,0xff,0xff,0xfc,
0x7f,0xff,0xfe,0x0,0xff,0xff,0xfc,
0xff,0xff,0xfc,0x0,0x7f,0xff,0xfe,
0x3f,0xff,0xf8,0x0,0x3f,0xff,0xf8,
0x1f,0xff,0xf0,0x0,0x1f,0xff,0xf0,
0xf,0xff,0xe0,0x0,0xf,0xff,0xe0,
0x7,0xff,0x80,0x0,0x3,0xff,0xc0,
0x7,0xff,0x80,0x0,0x3,0xff,0xc0,
0x1,0xff,0x0,0x0,0x1,0xff,0x0,
0x0,0xfe,0x0,0x0,0x0,0xfe,0x0,
0x0,0x7c,0x0,0x0,0x0,0x7c,0x0,
0x0,0x38,0x0,0x0,0x0,0x38,0x0,
0x0,0x20,0x0,0x0,0x0,0x8,0x0 }
};
#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
#include <Adafruit_CC3000.h>
#include <ccspi.h>
//#include <SPI.h>
#include <string.h>
#include "utility/debug.h"
#define GET_IP_SERVER cc3000.IP2U32(192, 168, 1, 81);
#define PORT_SERVER 80
#define REFRESH_DELAY 1800000 // 30min
#define ADAFRUIT_CC3000_IRQ 3
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIVIDER);
// #define WLAN_SSID "YourWiFiSsid" // cannot be longer than 32 characters!
#if ! defined(WLAN_SSID)
#error("Please define WLAN_SSID like the line above");
#endif
// #define WLAN_PASS "YourWiFiPassword"
#if ! defined(WLAN_PASS)
#error("Please define WLAN_PASS like the line above");
#endif
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY WLAN_SEC_WPA2
#define IDLE_TIMEOUT_MS 3000
#define LOCATION_WEBSITE "ip-api.com"
#define LOCATION_WEBPAGE "/json"
#define LAT_BUFFER_SIZE 20
char latBuffer[LAT_BUFFER_SIZE];
#define LAT_PREFIX_SIZE 6
static const char latPrefix[] = {'"', 'l', 'a', 't', '"', ':'};
#define LAT_LAST_CHAR ','
#define LON_BUFFER_SIZE 20
char lonBuffer[LAT_BUFFER_SIZE];
#define LON_PREFIX_SIZE 6
static const char lonPrefix[] = {'"', 'l', 'o', 'n', '"', ':'};
#define LON_LAST_CHAR ','
#define CITY_BUFFER_SIZE 30
char cityBuffer[CITY_BUFFER_SIZE];
#define CITY_PREFIX_SIZE 8
static const char cityPrefix[] = {'"', 'c', 'i', 't', 'y', '"', ':', '"'};
#define CITY_LAST_CHAR '"'
#define WEATHER_WEBSITE "api.wunderground.com"
#define WEATHER_WEBPAGE_BUFFER_SIZE 150
char weatherWebpageBuffer[WEATHER_WEBPAGE_BUFFER_SIZE];
// #define WUNDERGROUND_API_KEY "YourKey" // get for free http://www.wunderground.com/weather/api/d/pricing.html
#if ! defined(WUNDERGROUND_API_KEY)
#error("Please define WUNDERGROUND_API_KEY like the line above");
#endif
#define TEMP_BUFFER_SIZE 13
char tempBuffer[TEMP_BUFFER_SIZE];
#define TEMP_PREFIX_SIZE 9
static const char tempPrefix[] = {'"', 't', 'e', 'm', 'p', '_', 'c', '"', ':'};
#define TEMP_LAST_CHAR_1 ','
#define TEMP_LAST_CHAR_2 '.'
#define ICON_BUFFER_SIZE 40
char iconBuffer[ICON_BUFFER_SIZE];
#define ICON_PREFIX_SIZE 8
static const char iconPrefix[] = {'"', 'i', 'c', 'o', 'n', '"', ':', '"'};
#define ICON_LAST_CHAR '"'
void setup(void)
{
Serial.begin(9600);
Serial.println("\nWelcome on Wireless Widget!");
displayInit();
diplayStatus("CONNECTION", "WIFI", ICON_LOAD);
Serial.print("Free RAM: "); Serial.println(getFreeRam(), DEC);
Serial.println(F("\nInitializing cc3000..."));
if (!cc3000.begin())
{
Serial.println(F("Couldn't begin()! Check your wiring?"));
while(1);
}
Serial.print(F("Attempting to connect to ")); Serial.println(WLAN_SSID);
if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
Serial.println(F("Failed!"));
while(1);
}
/* Wait for DHCP to complete */
Serial.println(F("Request DHCP"));
while (!cc3000.checkDHCP())
{
delay(100); // ToDo: Insert a DHCP timeout!
}
}
void loop(void)
{
diplayStatus("LOCATION", "DATA", ICON_LOAD);
Serial.println(F("-------------------------------------"));
if (getLocation()) {
diplayStatus("WEATHER", "DATA", ICON_LOAD);
weatherWebpageBuffer[0] = '\0';
strcat(weatherWebpageBuffer, "/api/");
strcat(weatherWebpageBuffer, WUNDERGROUND_API_KEY);
strcat(weatherWebpageBuffer, "/conditions/q/");
strcat(weatherWebpageBuffer, latBuffer);
strcat(weatherWebpageBuffer, ",");
strcat(weatherWebpageBuffer, lonBuffer);
strcat(weatherWebpageBuffer, ".json");
Serial.print("\nweather webpage: ");Serial.println(weatherWebpageBuffer);
if (weatherFromMyServer()){
displayInit();
diplayWeather();
}
else{
displayInit();
diplayStatus("WEATHER", "DATA", ICON_ERROR);
}
}
else{
displayInit();
diplayStatus("LOCATION", "DATA", ICON_ERROR);
}
delay(REFRESH_DELAY);
}
void displayInit(){
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.display();
}
void diplayWeather(){
display.clearDisplay();
// city
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println(cityBuffer);
display.display();
// icon
unsigned char icon = iconNameToNumber(iconBuffer);
display.drawBitmap(IMAGE_OFFSET_X, IMAGE_OFFSET_Y, images[icon], IMAGE_WIDTH, IMAGE_HEIGHT, 1);
display.display();
// temp
unsigned char tempLen = 0, i = 0;
while (i < TEMP_BUFFER_SIZE) {
if (tempBuffer[i++] == '\0'){
break;
}
tempLen++;
}
display.setTextSize(3);
display.setTextColor(WHITE);
display.setCursor(0,24);
display.println(tempBuffer);
display.display();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(tempLen * DISPLAY_CHAR_SIZE * 3, TEMP_OFFSET_Y);
display.println("o");
display.display();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(tempLen * DISPLAY_CHAR_SIZE * 3 + DISPLAY_CHAR_SIZE, TEMP_OFFSET_Y + 2);
display.println("C");
display.display();
}
void diplayStatus(char *title, char *message, unsigned char iconPosition){
display.clearDisplay();
// city
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println(title);
display.display();
// icon
display.drawBitmap(IMAGE_OFFSET_X, IMAGE_OFFSET_Y, images[iconPosition], IMAGE_WIDTH, IMAGE_HEIGHT, 1);
display.display();
// temp
display.setTextSize(3);
display.setTextColor(WHITE);
display.setCursor(0,24);
display.println(message);
display.display();
}
/*
* return 1 if data from the webservice is ok
* return 0 if data from the webservice is corupted
*/
unsigned char weatherFromMyServer(){
uint32_t ip = 0;
Serial.print(WEATHER_WEBSITE); Serial.print(F(" -> "));
while (ip == 0) {
if (! cc3000.getHostByName(WEATHER_WEBSITE, &ip)) {
Serial.println(F("Couldn't resolve!"));
}
delay(500);
}
cc3000.printIPdotsRev(ip);Serial.println("");
Adafruit_CC3000_Client www = cc3000.connectTCP(ip, 80);
if (www.connected()) {
www.fastrprint(F("GET "));
www.fastrprint(weatherWebpageBuffer);
www.fastrprint(F(" HTTP/1.1\r\n"));
www.fastrprint(F("Host: ")); www.fastrprint(WEATHER_WEBSITE); www.fastrprint(F("\r\n"));
www.fastrprint(F("\r\n"));
www.println();
} else {
Serial.println(F("Connection failed"));
return 0;
}
unsigned char tempIndex = 0;
char foundTemp = 0;
unsigned char iconIndex = 0;
char foundIcon = 0;
unsigned long lastRead = millis();
while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
while (www.available()) {
char c = www.read();
// parse temp
jsonParser(c, tempBuffer, TEMP_BUFFER_SIZE, &tempIndex, &foundTemp, tempPrefix, TEMP_PREFIX_SIZE, TEMP_LAST_CHAR_1, TEMP_LAST_CHAR_2, 0);
// parse icon
jsonParser(c, iconBuffer, ICON_BUFFER_SIZE, &iconIndex, &foundIcon, iconPrefix, ICON_PREFIX_SIZE, ICON_LAST_CHAR, ICON_LAST_CHAR, 0);
lastRead = millis();
}
}
www.close();
if (foundTemp && foundIcon){
Serial.print(F("Temp: "));Serial.println(tempBuffer);
Serial.print(F("Icon: "));Serial.println(iconBuffer);
return 1;
}
else{
Serial.println(F("Error to get data from Weather"));
return 0;
}
}
/*
* return 1 if data from the webservice is ok
* return 0 if data from the webservice is corupted
*/
unsigned char getLocation(){
uint32_t ip = 0;
Serial.print(LOCATION_WEBSITE); Serial.print(F(" -> "));
while (ip == 0) {
if (! cc3000.getHostByName(LOCATION_WEBSITE, &ip)) {
Serial.println(F("Couldn't resolve!"));
}
delay(500);
}
cc3000.printIPdotsRev(ip);Serial.println("");
Adafruit_CC3000_Client www = cc3000.connectTCP(ip, 80);
if (www.connected()) {
www.fastrprint(F("GET "));
www.fastrprint(LOCATION_WEBPAGE);
www.fastrprint(F(" HTTP/1.1\r\n"));
www.fastrprint(F("Host: ")); www.fastrprint(LOCATION_WEBSITE); www.fastrprint(F("\r\n"));
www.fastrprint(F("\r\n"));
www.println();
} else {
Serial.println(F("Connection failed"));
return 0;
}
unsigned char latIndex = 0;
char foundLat = 0;
unsigned char lonIndex = 0;
char foundLon = 0;
unsigned char cityIndex = 0;
char foundCity = 0;
unsigned long lastRead = millis();
while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
while (www.available()) {
char c = www.read();
// parse lat
jsonParser(c, latBuffer, LAT_BUFFER_SIZE, &latIndex, &foundLat, latPrefix, LAT_PREFIX_SIZE, LAT_LAST_CHAR, LAT_LAST_CHAR, 0);
// parse lon
jsonParser(c, lonBuffer, LON_BUFFER_SIZE, &lonIndex, &foundLon, lonPrefix, LON_PREFIX_SIZE, LON_LAST_CHAR, LON_LAST_CHAR, 0);
// parse city
jsonParser(c, cityBuffer, CITY_BUFFER_SIZE, &cityIndex, &foundCity, cityPrefix, CITY_PREFIX_SIZE, CITY_LAST_CHAR, CITY_LAST_CHAR, 1);
lastRead = millis();
}
}
www.close();
if (foundLat && foundLon && foundCity){
Serial.print(F("City: "));Serial.println(cityBuffer);
Serial.print(F("Lat: "));Serial.println(latBuffer);
Serial.print(F("Lon: "));Serial.println(lonBuffer);
return 1;
}
else{
Serial.println(F("Error to get data from location"));
return 0;
}
}
void jsonParser(char c, char *buffer, int bufferSize, unsigned char *index, char *found, const char *prefix, int prefixSize, char lastChar1, char lastChar2, unsigned char toUpperCase){
if ((*index) < bufferSize){
buffer[(*index)++] = c;
}
else if (! *found){
for (int i = 0; i < bufferSize - 1; i++){
buffer[i] = buffer[i + 1];
}
buffer[bufferSize - 1] = c;
char prefixFound = 1;
int i = 0;
if (prefixSize > bufferSize){
prefixFound = 0;
}
while ((i < prefixSize) && prefixFound){
if (buffer[i] != (prefix[i++])){
prefixFound = 0;
}
}
if (prefixFound){
*found = 1;
// prefixABClastchar => ABC\0
for (int j = 0; j < prefixSize; j++){
for (int i = 0; i < bufferSize - 1; i++){
if ((j == prefixSize - 1) && (toUpperCase) && ( 'a' <= buffer[i + 1]) && (buffer[i + 1] <= 'z')){
buffer[i] = buffer[ i + 1] - 32; // to upper case
}
else{
buffer[i] = buffer[i + 1];
}
}
}
int i = 1;
char suffixFound = 0;
while ((i < bufferSize) && (! suffixFound)){
if ((buffer[i] == lastChar1) || (buffer[i] == lastChar2)){
suffixFound = 1;
buffer[i] = '\0';
}
i++;
}
if (! suffixFound){
buffer[bufferSize - 1] = '\0';
}
}
}
}
unsigned char iconNameToNumber(char *name){
if ((strcmp(name, "chanceflurries") == 0) || (strcmp(name, "chancesleet") == 0) || (strcmp(name, "chancesnow") == 0)
|| (strcmp(name, "flurries") == 0) || (strcmp(name, "sleet") == 0) || (strcmp(name, "snow") == 0)) {
return ICON_SNOW;
}
else if ((strcmp(name, "chancerain") == 0) || (strcmp(name, "chancetstorms") == 0) || (strcmp(name, "rain") == 0)
|| (strcmp(name, "tstorms") == 0)){
return ICON_RAIN;
}
else if ((strcmp(name, "clear") == 0) || (strcmp(name, "hazy") == 0) || (strcmp(name, "sunny") == 0)){
return ICON_SUN;
}
else if ((strcmp(name, "cloudy") == 0) || (strcmp(name, "fog") == 0) || (strcmp(name, "unknown") == 0)
|| (strcmp(name, "partlycloudy") == 0)){
return ICON_CLOUD;
}
else{
return ICON_CLOUD_SUN;
}
}
Comments