summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--.travis.yml67
-rw-r--r--.vscode/extensions.json7
-rw-r--r--include/README39
-rw-r--r--lib/Arduino_I2C_Port_Expander/src/Arduino_I2C_Port_Expander.cpp92
-rw-r--r--lib/Arduino_I2C_Port_Expander/src/Arduino_I2C_Port_Expander.h31
-rw-r--r--lib/README46
-rw-r--r--platformio.ini21
-rw-r--r--src/main.cpp261
-rw-r--r--test/README11
10 files changed, 581 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2de98ab
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+.pio
+.pioenvs
+.piolibdeps
+.vscode/.browse.c_cpp.db*
+.vscode/c_cpp_properties.json
+.vscode/launch.json
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..7c486f1
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,67 @@
+# Continuous Integration (CI) is the practice, in software
+# engineering, of merging all developer working copies with a shared mainline
+# several times a day < https://docs.platformio.org/page/ci/index.html >
+#
+# Documentation:
+#
+# * Travis CI Embedded Builds with PlatformIO
+# < https://docs.travis-ci.com/user/integration/platformio/ >
+#
+# * PlatformIO integration with Travis CI
+# < https://docs.platformio.org/page/ci/travis.html >
+#
+# * User Guide for `platformio ci` command
+# < https://docs.platformio.org/page/userguide/cmd_ci.html >
+#
+#
+# Please choose one of the following templates (proposed below) and uncomment
+# it (remove "# " before each line) or use own configuration according to the
+# Travis CI documentation (see above).
+#
+
+
+#
+# Template #1: General project. Test it using existing `platformio.ini`.
+#
+
+# language: python
+# python:
+# - "2.7"
+#
+# sudo: false
+# cache:
+# directories:
+# - "~/.platformio"
+#
+# install:
+# - pip install -U platformio
+# - platformio update
+#
+# script:
+# - platformio run
+
+
+#
+# Template #2: The project is intended to be used as a library with examples.
+#
+
+# language: python
+# python:
+# - "2.7"
+#
+# sudo: false
+# cache:
+# directories:
+# - "~/.platformio"
+#
+# env:
+# - PLATFORMIO_CI_SRC=path/to/test/file.c
+# - PLATFORMIO_CI_SRC=examples/file.ino
+# - PLATFORMIO_CI_SRC=path/to/test/directory
+#
+# install:
+# - pip install -U platformio
+# - platformio update
+#
+# script:
+# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..0f0d740
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,7 @@
+{
+ // See http://go.microsoft.com/fwlink/?LinkId=827846
+ // for the documentation about the extensions.json format
+ "recommendations": [
+ "platformio.platformio-ide"
+ ]
+}
diff --git a/include/README b/include/README
new file mode 100644
index 0000000..194dcd4
--- /dev/null
+++ b/include/README
@@ -0,0 +1,39 @@
+
+This directory is intended for project header files.
+
+A header file is a file containing C declarations and macro definitions
+to be shared between several project source files. You request the use of a
+header file in your project source file (C, C++, etc) located in `src` folder
+by including it, with the C preprocessing directive `#include'.
+
+```src/main.c
+
+#include "header.h"
+
+int main (void)
+{
+ ...
+}
+```
+
+Including a header file produces the same results as copying the header file
+into each source file that needs it. Such copying would be time-consuming
+and error-prone. With a header file, the related declarations appear
+in only one place. If they need to be changed, they can be changed in one
+place, and programs that include the header file will automatically use the
+new version when next recompiled. The header file eliminates the labor of
+finding and changing all the copies as well as the risk that a failure to
+find one copy will result in inconsistencies within a program.
+
+In C, the usual convention is to give header files names that end with `.h'.
+It is most portable to use only letters, digits, dashes, and underscores in
+header file names, and at most one dot.
+
+Read more about using header files in official GCC documentation:
+
+* Include Syntax
+* Include Operation
+* Once-Only Headers
+* Computed Includes
+
+https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
diff --git a/lib/Arduino_I2C_Port_Expander/src/Arduino_I2C_Port_Expander.cpp b/lib/Arduino_I2C_Port_Expander/src/Arduino_I2C_Port_Expander.cpp
new file mode 100644
index 0000000..70470e9
--- /dev/null
+++ b/lib/Arduino_I2C_Port_Expander/src/Arduino_I2C_Port_Expander.cpp
@@ -0,0 +1,92 @@
+#include "Arduino_I2C_Port_Expander.h" //include the declaration for this class
+
+byte io_DataPacket[3];
+byte io_pin;
+byte io_method;
+byte io_value;
+uint8_t _addr;
+
+//<<constructor>>
+EXPAND::EXPAND(uint8_t addr){
+ _addr = addr;
+}
+
+//<<destructor>>
+EXPAND::~EXPAND(){/*nothing to destruct*/}
+
+void EXPAND::digitalWrite(byte pin,byte val){
+ io_DataPacket[0] = 1; // method
+ io_DataPacket[1] = pin; // pin
+ io_DataPacket[2] = val; // val
+ sendDataPacket();
+ int received = receiveResponse();
+}
+
+int EXPAND::digitalRead(byte pin){
+ io_DataPacket[0] = 2; // method
+ io_DataPacket[1] = pin; // pin
+ sendDataPacket();
+ int received = receiveResponse();
+ return received;
+}
+
+int EXPAND::digitalReadPullup(byte pin){
+ io_DataPacket[0] = 3; // method
+ io_DataPacket[1] = pin; // pin
+ sendDataPacket();
+ int received = receiveResponse();
+ return received;
+}
+
+void EXPAND::analogWrite(byte pin,byte val){
+ io_DataPacket[0] = 4; // method
+ io_DataPacket[1] = pin; // pin
+ io_DataPacket[2] = val; // val
+ sendDataPacket();
+ int received = receiveResponse();
+}
+
+int EXPAND::analogRead(byte pin){
+ io_DataPacket[0] = 5; // method
+ io_DataPacket[1] = pin; // pin
+ sendDataPacket();
+ int received = receiveResponse();
+ return received;
+}
+
+void EXPAND::analogWriteSlow(byte pin,byte val){
+ io_DataPacket[0] = 10; // method
+ io_DataPacket[1] = pin; // pin
+ io_DataPacket[2] = val; // val
+ sendDataPacket();
+ int received = receiveResponse();
+}
+
+
+void EXPAND::sendDataPacket(){
+ Wire.beginTransmission(_addr);
+ Wire.write(io_DataPacket, 3);
+ Wire.endTransmission(true);
+ delay(1);
+}
+
+int EXPAND::receiveResponse(){
+ unsigned int receivedValue;
+ int available = Wire.requestFrom(_addr, (byte)1);
+ byte buffer[2];
+ if(available == 1)
+ {
+ buffer[0] = Wire.read();
+ }
+ available = Wire.requestFrom(_addr, (byte)1);
+ if(available == 1)
+ {
+ buffer[1] = Wire.read();
+ }
+ receivedValue = buffer[0] << 8 | buffer[1];
+
+ return receivedValue;
+}
+
+
+
diff --git a/lib/Arduino_I2C_Port_Expander/src/Arduino_I2C_Port_Expander.h b/lib/Arduino_I2C_Port_Expander/src/Arduino_I2C_Port_Expander.h
new file mode 100644
index 0000000..9d9c2b2
--- /dev/null
+++ b/lib/Arduino_I2C_Port_Expander/src/Arduino_I2C_Port_Expander.h
@@ -0,0 +1,31 @@
+#ifndef EXPANDUINO_H
+#define EXPANDUINO_H
+
+#if ARDUINO >= 100
+ #include "Arduino.h"
+#else
+ #include "WProgram.h"
+#endif
+#include <Wire.h>
+
+class EXPAND {
+ public:
+ EXPAND(uint8_t addr);
+ ~EXPAND();
+ void digitalWrite(byte pin,byte val);
+ int digitalRead(byte pin);
+ int digitalReadPullup(byte pin);
+ void analogWrite(byte pin,byte val);
+ int analogRead(byte pin);
+ void sendDataPacket();
+ int receiveResponse();
+
+ void analogWriteSlow(byte pin,byte val);
+ private:
+ uint8_t _addr;
+};
+
+
+#endif
+
+
diff --git a/lib/README b/lib/README
new file mode 100644
index 0000000..6debab1
--- /dev/null
+++ b/lib/README
@@ -0,0 +1,46 @@
+
+This directory is intended for project specific (private) libraries.
+PlatformIO will compile them to static libraries and link into executable file.
+
+The source code of each library should be placed in a an own separate directory
+("lib/your_library_name/[here are source files]").
+
+For example, see a structure of the following two libraries `Foo` and `Bar`:
+
+|--lib
+| |
+| |--Bar
+| | |--docs
+| | |--examples
+| | |--src
+| | |- Bar.c
+| | |- Bar.h
+| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
+| |
+| |--Foo
+| | |- Foo.c
+| | |- Foo.h
+| |
+| |- README --> THIS FILE
+|
+|- platformio.ini
+|--src
+ |- main.c
+
+and a contents of `src/main.c`:
+```
+#include <Foo.h>
+#include <Bar.h>
+
+int main (void)
+{
+ ...
+}
+
+```
+
+PlatformIO Library Dependency Finder will find automatically dependent
+libraries scanning project source files.
+
+More information about PlatformIO Library Dependency Finder
+- https://docs.platformio.org/page/librarymanager/ldf.html
diff --git a/platformio.ini b/platformio.ini
new file mode 100644
index 0000000..3372bc3
--- /dev/null
+++ b/platformio.ini
@@ -0,0 +1,21 @@
+; PlatformIO Project Configuration File
+;
+; Build options: build flags, source filter
+; Upload options: custom upload port, speed and extra flags
+; Library options: dependencies, extra library storages
+; Advanced options: extra scripting
+;
+; Please visit documentation for the other options and examples
+; https://docs.platformio.org/page/projectconf.html
+
+[env:d1_mini]
+platform = espressif8266
+board = d1_mini
+framework = arduino
+#upload_port = /dev/ttyUSB3
+upload_protocol = espota
+upload_port = 172.19.1.80
+upload_flags= -P 36286
+
+lib_deps =
+ PubSubClient
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..ccd53fc
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,261 @@
+#include <Arduino.h>
+#include <Arduino_I2C_Port_Expander.h>
+
+#include <ESP8266WiFi.h>
+#include <ESP8266mDNS.h>
+#include <WiFiUdp.h>
+#include <ArduinoOTA.h>
+#include <EEPROM.h>
+
+#include <PubSubClient.h>
+const char* debug = "debug";
+const char* server = "172.19.1.10";
+
+const char* s_will = "died";
+const char* s_on = "on";
+const char* s_off = "off";
+
+const char* on[6] = {"led0:on","led1:on","led2:on","led3:on","led4:on","led5:on"};
+const char* off[6] = {"led0:off","led1:off","led2:off","led3:off","led4:off","led5:off"};
+int timer[6] = {0,0,0,0,0,0};
+int button_lvl[6] = {0,0,0,0,0,0};
+char button[6][23];
+char led[6][23];
+
+const char* s_error = "error";
+const char* s_ready = "ready";
+
+WiFiClient espClient;
+PubSubClient client(espClient);
+
+const char* ssid = "iot";
+const char* password = "longtimeago";
+
+EXPAND io1(0x01);
+EXPAND io2(0x02);
+
+int wait = 1;
+unsigned int i;
+int val;
+char str[10];
+unsigned long tick = 0;
+unsigned long tock = 0;
+
+uint8_t MAC_array[6];
+char MAC_char[23];
+char buffer[60];
+char sta[23];
+char lim[23];
+
+
+int level(byte* payload, unsigned int length) {
+ if ((char)payload[0] == 'o' && (char)payload[1] == 'n') {
+ return 255;
+ }
+ if ((char)payload[0] == 'o' && (char)payload[1] == 'f') {
+ return 0;
+ }
+
+ str[0] = '0';
+ str[1] = '0';
+ str[2] = '0';
+ str[3] = '0';
+ str[4] = '\0';
+
+ for (i = 0; i < length; i++) {
+ str[i] = (char)payload[i];
+ }
+
+ for (i = length; i < 10; i++) {
+ str[i] = '\0';
+ }
+
+ return atoi(str);
+}
+
+void callback(char* topic, byte* payload, unsigned int length) {
+
+ // debug reboot of device
+ if(topic[0] == 'd')
+ {
+ if((char)payload[0] == 'r' && (char)payload[1] == 'e' && (char)payload[2] == 's' && (char)payload[3] == 'e' && (char)payload[4] == 't')
+ {
+ WiFi.forceSleepBegin();
+ ESP.wdtFeed();
+ ESP.restart();
+ while(true)
+ {
+ yield();
+ }
+ }
+ return ;
+ }
+
+ // set limt
+ if(topic[14] == 'l' && topic[15] == 'i')
+ {
+ int tmp = level(payload, length);
+ if(tmp > 0)
+ {
+ wait = tmp;
+ EEPROM.write(0,wait);
+ EEPROM.commit();
+ sprintf(buffer,"%d",wait);
+ client.publish(sta,buffer);
+ }
+ else
+ {
+ client.publish(sta,s_error);
+ }
+ return ;
+ }
+
+
+ i = ((int)topic[17]) - 48;
+
+ if(payload[0] == 't')
+ {
+ timer[i] = wait;
+ val = 255;
+ }
+ else
+ {
+ // string to int
+ val = level(payload,length);
+ }
+
+ if(topic[17] == '0' ) { io1.analogWriteSlow(3,val); }
+ if(topic[17] == '1' ) { io1.analogWriteSlow(5,val); }
+ if(topic[17] == '2' ) { io1.digitalWrite(6,val > 0 ? HIGH : LOW ); }
+ //if(topic[17] == '3' ) { io2.analogWriteSlow(3,val); }
+ //if(topic[17] == '4' ) { io2.analogWriteSlow(5,val); }
+ //if(topic[17] == '5' ) { io2.analogWriteSlow(6,val); }
+
+ if(val > 0) client.publish(sta, on[0]);
+ if(val == 0) client.publish(sta, off[0]);
+ return;
+
+}
+
+void trigger_input(int &current, int value, const char* topic)
+{
+ if(current != value)
+ {
+ current = value;
+ if(value == HIGH)
+ {
+ client.publish(topic, s_on);
+ }
+ else
+ {
+ client.publish(topic, s_off);
+ }
+ client.loop();
+ }
+}
+
+void setup() {
+ // put your setup code here, to run once:
+ Wire.setClock(10000L);
+ Wire.begin();
+
+ WiFi.mode(WIFI_STA);
+ WiFi.begin(ssid, password);
+
+ while (WiFi.status() != WL_CONNECTED) {
+ delay(10);
+ yield();
+ }
+
+ WiFi.macAddress(MAC_array);
+ for (i = 0; i < sizeof(MAC_array); ++i) {
+ sprintf(MAC_char, "%s%02x", MAC_char, MAC_array[i]);
+ }
+ sprintf(sta, "/%s/status", MAC_char);
+ sprintf(lim, "/%s/limit", MAC_char);
+
+ client.setServer(server, 1883);
+ client.setCallback(callback);
+ client.connect(MAC_char, sta, 0, false, s_will);
+ client.publish(debug, MAC_char);
+
+ EEPROM.begin(512);
+ wait = int(EEPROM.read(0));
+
+ for (i = 0; i < 6; i++)
+ {
+ sprintf(led[i], "/%s/led%i", MAC_char, i);
+ sprintf(button[i], "/%s/button%i", MAC_char, i);
+ client.subscribe(led[i],1);
+ }
+
+ client.publish(sta,__FILE__);
+ client.publish(sta,s_ready);
+ sprintf(buffer,"%d",wait);
+ client.publish(sta,buffer);
+ client.subscribe(lim,1);
+
+ IPAddress ip = WiFi.localIP();
+ sprintf(buffer,"%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
+ client.publish(sta,buffer);
+
+ ArduinoOTA.setHostname(MAC_char);
+ ArduinoOTA.begin();
+ ESP.wdtEnable(WDTO_8S);
+ tick = millis();
+ tock = millis();
+}
+
+void loop() {
+ // put your main code here, to run repeatedly:
+ ESP.wdtFeed();
+ ArduinoOTA.handle();
+ ESP.wdtFeed();
+
+ if (WiFi.status() != WL_CONNECTED) {
+ yield();
+ }
+
+ if (client.connected()) {
+ client.loop();
+ } else {
+ client.connect(MAC_char, sta, 0, false, s_will);
+ client.subscribe(debug,1);
+ client.subscribe(lim,1);
+ for (i = 0; i < 6; i++)
+ {
+ client.subscribe(led[i],1);
+ }
+ }
+
+ ESP.wdtFeed();
+ yield();
+
+ if(millis() - tick >= 20) {
+ tick = millis();
+
+ for (i = 0; i < 3; i++)
+ {
+ trigger_input(button_lvl[i],io1.digitalRead(14 + i), button[i]); yield();
+ //trigger_input(button_lvl[i+3],io2.digitalRead(14 + i), button[i+3]); yield();
+ }
+ }
+
+ // every secound
+ if(millis() - tock >= 1000) {
+ tock = millis();
+ for (i = 0; i < 6; i++)
+ {
+ if(timer[i] > 0)
+ {
+ timer[i]--;
+ if(timer[i] == 0)
+ {
+ client.publish(led[i],s_off,1);
+ }
+ }
+ }
+ }
+
+ delay(10);
+} \ No newline at end of file
diff --git a/test/README b/test/README
new file mode 100644
index 0000000..df5066e
--- /dev/null
+++ b/test/README
@@ -0,0 +1,11 @@
+
+This directory is intended for PIO Unit Testing and project tests.
+
+Unit Testing is a software testing method by which individual units of
+source code, sets of one or more MCU program modules together with associated
+control data, usage procedures, and operating procedures, are tested to
+determine whether they are fit for use. Unit testing finds problems early
+in the development cycle.
+
+More information about PIO Unit Testing:
+- https://docs.platformio.org/page/plus/unit-testing.html