mirror of
https://github.com/xg590/IoT.git
synced 2024-11-17 00:37:38 +03:00
rpi
This commit is contained in:
46
Board/Arduino_CLI.md
Normal file
46
Board/Arduino_CLI.md
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
### <a name="Arduino-CLI">Arduino-CLI:</a> Program Arduino board in CLI
|
||||
* Blink
|
||||
```
|
||||
wget arduino-cli_0.18.3_Linux_64bit.tar.gz && tar zxvf # https://github.com/arduino/arduino-cli/releases
|
||||
sudo mv arduino-cli /usr/local/bin/
|
||||
arduino-cli core install arduino:avr # Install compile platform of Arduino board family
|
||||
arduino-cli core update-index --additional-urls https://arduino.esp8266.com/stable/package_esp8266com_index.json
|
||||
arduino-cli core install esp8266:esp8266 --additional-urls https://arduino.esp8266.com/stable/package_esp8266com_index.json
|
||||
arduino-cli core update-index --additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
|
||||
arduino-cli core install esp32:esp32 --additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
|
||||
arduino-cli core update-index --additional-urls https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
|
||||
arduino-cli core install seeeduino:samd --additional-urls https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
|
||||
arduino-cli core update-index --additional-urls https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json
|
||||
arduino-cli core install sandeepmistry:nRF5 --additional-urls https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json
|
||||
arduino-cli board listall # You will see FQBN. What kind of board we can program now?
|
||||
mkdir /tmp/blink
|
||||
cd /tmp/blink
|
||||
cat << EOF > blink.ino
|
||||
int count = 0;
|
||||
void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(9600);}
|
||||
void loop() {
|
||||
count++; Serial.println(count);
|
||||
digitalWrite(LED_BUILTIN, HIGH); delay(1000);
|
||||
digitalWrite(LED_BUILTIN, LOW); delay(1000);
|
||||
}
|
||||
EOF
|
||||
arduino-cli compile . --fqbn arduino:avr:nano # Compile the blink test
|
||||
sudo usermod -aG dialout $USER # Give /dev/ttyUSB0 access permission to arduino-cli
|
||||
newgrp dialout
|
||||
arduino-cli upload . --fqbn arduino:avr:nano -p /dev/ttyUSB0
|
||||
```
|
||||
* Install library
|
||||
```
|
||||
arduino-cli lib search SHT4x
|
||||
arduino-cli lib install "Adafruit SHT4x Library"
|
||||
```
|
||||
* More
|
||||
```
|
||||
cat << EOF >> ~/.bashrc
|
||||
export PATH=\$PATH:~/bin
|
||||
alias xiao='arduino-cli compile . --fqbn Seeeduino:samd:seeed_XIAO_m0 && arduino-cli upload . --fqbn Seeeduino:samd:seeed_XIAO_m0 -p'
|
||||
alias d1_mini='arduino-cli compile . --fqbn esp8266:esp8266:d1_mini && arduino-cli upload . --fqbn esp8266:esp8266:d1_mini -p'
|
||||
alias bbc='arduino-cli compile . --fqbn sandeepmistry:nRF5:BBCmicrobit && arduino-cli upload . --fqbn sandeepmistry:nRF5:BBCmicrobit -p'
|
||||
EOF
|
||||
```
|
||||
26
Board/Espressif/esptool.md
Normal file
26
Board/Espressif/esptool.md
Normal file
@@ -0,0 +1,26 @@
|
||||
* Enable WSL in PowerShell
|
||||
```
|
||||
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
|
||||
```
|
||||
* Virtual Com Port in WSL (COM34 -> /dev/ttyS34)
|
||||
* Binary data can be written to the ESP’s flash chip via the serial <i><b>write_flash</b></i> command:
|
||||
* Multiple flash addresses and file names can be given on the same command line:
|
||||
```
|
||||
idf.py -p (PORT) flash
|
||||
```
|
||||
Or:
|
||||
```
|
||||
esptool.py
|
||||
-p (PORT)
|
||||
-b 460800
|
||||
--before default_reset
|
||||
--after hard_reset
|
||||
--chip esp32
|
||||
write_flash
|
||||
--flash_mode dio
|
||||
--flash_size detect
|
||||
--flash_freq 40m
|
||||
0x1000 build/bootloader/bootloader.bin
|
||||
0x8000 build/partition_table/partition-table.bin
|
||||
0x10000 build/blink.bin
|
||||
```
|
||||
@@ -1,61 +1,15 @@
|
||||
### Pin convention
|
||||
* For ESP8266, Digital Pin 4 (D4) is GPIO2
|
||||
* In Arduino IDE, pin is specified by on-board printed name like A0, A2, D1, or D3. Meanwhile, GPIO number is recommended for MicroPython (ESP8266) or Python (Raspberry Pi).
|
||||
* Following C code will light up built-in LED on ESP8266 dev board
|
||||
### Pin convention
|
||||
* For MCU D1 mini, D4 (digital pin 4) is GPIO2.
|
||||
* In Arduino IDE, pin is specified by on-board printed name like A0 (analog pin 0) and D4. Following C code will light up built-in LED on D1 mini.
|
||||
```C
|
||||
void setup() { pinMode(D4, OUTPUT); digitalWrite(D4, 0); }
|
||||
void loop () {}
|
||||
```
|
||||
* Following MicroPython code also light up built-in LED on ESP8266 dev board
|
||||
```
|
||||
* Meanwhile, MicroPython (ESP8266) or Python (Raspberry Pi) recommends GPIO number. Following MicroPython code also lights up built-in LED on D1 mini.
|
||||
```Python
|
||||
from machine import Pin
|
||||
Pin( 2, Pin.OUT, value=0)
|
||||
```
|
||||
### <a name="Arduino-CLI">Arduino-CLI:</a> Program Arduino board on Raspberry Pi
|
||||
* Blink
|
||||
```
|
||||
wget arduino-cli_0.18.3_Linux_64bit.tar.gz && tar zxvf # https://github.com/arduino/arduino-cli/releases
|
||||
sudo mv arduino-cli /usr/local/bin/
|
||||
arduino-cli core install arduino:avr # Install compile platform of Arduino board family
|
||||
arduino-cli core update-index --additional-urls https://arduino.esp8266.com/stable/package_esp8266com_index.json
|
||||
arduino-cli core install esp8266:esp8266 --additional-urls https://arduino.esp8266.com/stable/package_esp8266com_index.json
|
||||
arduino-cli core update-index --additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
|
||||
arduino-cli core install esp32:esp32 --additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
|
||||
arduino-cli core update-index --additional-urls https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
|
||||
arduino-cli core install seeeduino:samd --additional-urls https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
|
||||
arduino-cli core update-index --additional-urls https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json
|
||||
arduino-cli core install sandeepmistry:nRF5 --additional-urls https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json
|
||||
arduino-cli board listall # You will see FQBN. What kind of board we can program now?
|
||||
mkdir /tmp/blink
|
||||
cd /tmp/blink
|
||||
cat << EOF > blink.ino
|
||||
int count = 0;
|
||||
void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(9600);}
|
||||
void loop() {
|
||||
count++; Serial.println(count);
|
||||
digitalWrite(LED_BUILTIN, HIGH); delay(1000);
|
||||
digitalWrite(LED_BUILTIN, LOW); delay(1000);
|
||||
}
|
||||
EOF
|
||||
arduino-cli compile . --fqbn arduino:avr:nano # Compile the blink test
|
||||
sudo usermod -aG dialout $USER # Give /dev/ttyUSB0 access permission to arduino-cli
|
||||
newgrp dialout
|
||||
arduino-cli upload . --fqbn arduino:avr:nano -p /dev/ttyUSB0
|
||||
```
|
||||
* Install library
|
||||
```
|
||||
arduino-cli lib search SHT4x
|
||||
arduino-cli lib install "Adafruit SHT4x Library"
|
||||
```
|
||||
* More
|
||||
```
|
||||
cat << EOF >> ~/.bashrc
|
||||
export PATH=\$PATH:~/bin
|
||||
alias xiao='arduino-cli compile . --fqbn Seeeduino:samd:seeed_XIAO_m0 && arduino-cli upload . --fqbn Seeeduino:samd:seeed_XIAO_m0 -p'
|
||||
alias d1_mini='arduino-cli compile . --fqbn esp8266:esp8266:d1_mini && arduino-cli upload . --fqbn esp8266:esp8266:d1_mini -p'
|
||||
alias bbc='arduino-cli compile . --fqbn sandeepmistry:nRF5:BBCmicrobit && arduino-cli upload . --fqbn sandeepmistry:nRF5:BBCmicrobit -p'
|
||||
EOF
|
||||
```
|
||||
### Trouble shooting
|
||||
* error while loading shared libraries: libfl.so.2
|
||||
```
|
||||
|
||||
@@ -189,7 +189,7 @@ Device Boot Start End Sectors Size Id
|
||||
mkdir /tmp/raspbian_os_boot
|
||||
sudo mount -o offset=$((8192*512)),umask=0002,uid=$UID $img /tmp/raspbian_os_boot
|
||||
```
|
||||
* Add / Change files
|
||||
* [Add / Change files](https://www.raspberrypi.com/news/raspberry-pi-bullseye-update-april-2022/)
|
||||
```
|
||||
touch /tmp/raspbian_os_boot/ssh # Enable ssh server at first boot
|
||||
cat << EOF > /tmp/raspbian_os_boot/wpa_supplicant.conf # Join WiFi network
|
||||
@@ -202,6 +202,9 @@ Device Boot Start End Sectors Size Id
|
||||
key_mgmt=WPA-PSK
|
||||
}
|
||||
EOF
|
||||
cat << EOF > /tmp/raspbian_os_boot/userconf.txt
|
||||
pi:$(echo 'raspberry' | openssl passwd -6 -stdin)
|
||||
EOF
|
||||
umount /tmp/raspbian_os_boot
|
||||
```
|
||||
* Mount system partition (Second partition is EXT4 format)
|
||||
|
||||
54
Misc/mqtt.md
Normal file
54
Misc/mqtt.md
Normal file
@@ -0,0 +1,54 @@
|
||||
### Broker
|
||||
* Mosquitto from Eclipse, written in C
|
||||
```
|
||||
sudo apt install -y mosquitto mosquitto-clients
|
||||
mosquitto -v
|
||||
sudo tee -a /etc/mosquitto/mosquitto.conf << EOF >/dev/null
|
||||
|
||||
listener 1883
|
||||
allow_anonymous true
|
||||
EOF
|
||||
sudo systemctl restart mosquitto.service
|
||||
```
|
||||
### Client
|
||||
* Install
|
||||
```
|
||||
sudo apt install -y mosquitto-clients
|
||||
```
|
||||
* Subscribe
|
||||
```
|
||||
mosquitto_sub -d -t testTopic
|
||||
```
|
||||
* Push
|
||||
```
|
||||
mosquitto_pub -h 192.168.xxx.xxx -t testTopic -m "Hello world!"
|
||||
```
|
||||
### Python
|
||||
```
|
||||
pip install paho-mqtt
|
||||
|
||||
import paho.mqtt.client as mqtt
|
||||
|
||||
client = mqtt.Client()
|
||||
client.connect("192.168.xxx.xxx", 1883, 60)
|
||||
client.publish("testTopic", payload="Hello World From Python", qos=0, retain=False)
|
||||
```
|
||||
### MicroPython
|
||||
[MQTT Lib](https://raw.githubusercontent.com/micropython/micropython-lib/master/micropython/umqtt.simple/umqtt/simple.py)
|
||||
```
|
||||
import time
|
||||
from umqtt.simple import MQTTClient
|
||||
|
||||
def sub_cb(topic, msg):
|
||||
print((topic, msg))
|
||||
|
||||
c = MQTTClient("client_id", "server_ip")
|
||||
c.set_callback(sub_cb)
|
||||
c.connect()
|
||||
c.subscribe(b"foo_topic")
|
||||
try:
|
||||
while 1:
|
||||
c.wait_msg()
|
||||
finally:
|
||||
c.disconnect()
|
||||
```
|
||||
119
Project/SHT4x/SHT4x.ino
Normal file
119
Project/SHT4x/SHT4x.ino
Normal file
@@ -0,0 +1,119 @@
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
#include "Adafruit_SHT4x.h"
|
||||
#include "env.h"
|
||||
/*
|
||||
cat << EOF > env.h
|
||||
#define STASSID "wifi_ssid"
|
||||
#define STAPSK "wifi_passwd"
|
||||
#define LOG_URL "http://192.168.x.x:x/log"
|
||||
EOF
|
||||
*/
|
||||
const int sensorPin = A0, OLED_SDA = D2, OLED_SCL = D1;
|
||||
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
|
||||
|
||||
void initWIFI() {
|
||||
WiFi.begin(STASSID, STAPSK);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.print("\nConnected! IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
delay(3000);
|
||||
http.begin(client, LOG_URL); //HTTP
|
||||
}
|
||||
|
||||
void initSHT4x() {
|
||||
Serial.println("Adafruit SHT4x test");
|
||||
if (! sht4.begin()) {
|
||||
Serial.println("Couldn't find SHT4x");
|
||||
while (1) delay(1);
|
||||
}
|
||||
Serial.println("Found SHT4x sensor");
|
||||
Serial.print("Serial number 0x");
|
||||
Serial.println(sht4.readSerial(), HEX);
|
||||
|
||||
// You can have 3 different precisions, higher precision takes longer
|
||||
sht4.setPrecision(SHT4X_HIGH_PRECISION);
|
||||
switch (sht4.getPrecision()) {
|
||||
case SHT4X_HIGH_PRECISION:
|
||||
Serial.println("High precision");
|
||||
break;
|
||||
case SHT4X_MED_PRECISION:
|
||||
Serial.println("Med precision");
|
||||
break;
|
||||
case SHT4X_LOW_PRECISION:
|
||||
Serial.println("Low precision");
|
||||
break;
|
||||
}
|
||||
|
||||
// You can have 6 different heater settings
|
||||
// higher heat and longer times uses more power
|
||||
// and reads will take longer too!
|
||||
sht4.setHeater(SHT4X_NO_HEATER);
|
||||
switch (sht4.getHeater()) {
|
||||
case SHT4X_NO_HEATER:
|
||||
Serial.println("No heater");
|
||||
break;
|
||||
case SHT4X_HIGH_HEATER_1S:
|
||||
Serial.println("High heat for 1 second");
|
||||
break;
|
||||
case SHT4X_HIGH_HEATER_100MS:
|
||||
Serial.println("High heat for 0.1 second");
|
||||
break;
|
||||
case SHT4X_MED_HEATER_1S:
|
||||
Serial.println("Medium heat for 1 second");
|
||||
break;
|
||||
case SHT4X_MED_HEATER_100MS:
|
||||
Serial.println("Medium heat for 0.1 second");
|
||||
break;
|
||||
case SHT4X_LOW_HEATER_1S:
|
||||
Serial.println("Low heat for 1 second");
|
||||
break;
|
||||
case SHT4X_LOW_HEATER_100MS:
|
||||
Serial.println("Low heat for 0.1 second");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
delay(10); // will pause Zero, Leonardo, etc until serial console opens
|
||||
Serial.print("\n\n\n");
|
||||
|
||||
pinMode(sensorPin, INPUT);
|
||||
|
||||
initWIFI();
|
||||
initSHT4x();
|
||||
}
|
||||
|
||||
float T, H; int P;
|
||||
void loop() {
|
||||
// wait for WiFi connection
|
||||
if ((WiFi.status() == WL_CONNECTED)) {
|
||||
sensors_event_t humidity, temp;
|
||||
sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
|
||||
T = temp.temperature;
|
||||
H = humidity.relative_humidity;
|
||||
P = analogRead(sensorPin);
|
||||
char json[96];
|
||||
sprintf(json,"{\"Temperature (C)\":%f,\"Humidity (%% rH)\":%f,\"Photoresistor\":%d}", T, H, P);
|
||||
Serial.println("[HTTP] POSTing "+String(json));
|
||||
http.addHeader("Content-Type", "application/json");
|
||||
int httpCode = http.POST(json);
|
||||
if (httpCode == HTTP_CODE_OK) {
|
||||
// const String& payload = http.getString();
|
||||
Serial.print("[HTTP] Payload received~\n\n");
|
||||
} else {
|
||||
Serial.printf("[HTTP] Problematic returncode: %s\n\n", http.errorToString(httpCode).c_str());
|
||||
}
|
||||
}
|
||||
delay(3000);
|
||||
}
|
||||
|
||||
// http.end();
|
||||
71
Project/SHT4x/plot.ipynb
Normal file
71
Project/SHT4x/plot.ipynb
Normal file
File diff suppressed because one or more lines are too long
408
Project/SHT4x/server.ipynb
Normal file
408
Project/SHT4x/server.ipynb
Normal file
@@ -0,0 +1,408 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "7ab5ee43",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2022-08-31T07:49:25.947790Z",
|
||||
"start_time": "2022-08-31T07:49:25.929995Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#pip install python-kasa flask requests picamera"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "72ac21ad",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2022-08-31T07:49:27.011462Z",
|
||||
"start_time": "2022-08-31T07:49:25.963467Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import sqlite3, datetime, time, queue, threading, sys, os, asyncio, kasa, pathlib, json, dateutil, requests, flask, logging # dhcp-lease-list\n",
|
||||
"\n",
|
||||
"'''\n",
|
||||
"with open('secret.json','w') as fw: \n",
|
||||
" sec = {'bedroom_bulb_ip':\"192.168.x.x\",\n",
|
||||
" 'bedroom_ac_ip' :\"192.168.x.x\" } \n",
|
||||
" json.dump(sec, fw)\n",
|
||||
"'''\n",
|
||||
"with open('secret.json') as fr: sec = json.load(fr) "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "1e2ccf4a",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2022-08-31T07:49:27.075754Z",
|
||||
"start_time": "2022-08-31T07:49:27.022444Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pathlib.Path('log').mkdir(parents=True, exist_ok=True)\n",
|
||||
"new_db = f'log/SHT40.{datetime.datetime.fromtimestamp(time.time()).strftime(\"%Y-%m-%dT%H:%M:%S\")}.db' \n",
|
||||
"\n",
|
||||
"def database(): \n",
|
||||
" con = sqlite3.connect(new_db) \n",
|
||||
" cur = con.cursor() \n",
|
||||
" cur.execute('CREATE TABLE IF NOT EXISTS log (Temperature REAL, Humidity REAL, Photoresistor INTEGER, timestamp REAL);')\n",
|
||||
" cur = con.cursor() \n",
|
||||
" while True: \n",
|
||||
" opt, foo = q_in.get() # q.get() = opt_foo\n",
|
||||
" bar = False # opt is a placeholder \n",
|
||||
" try:\n",
|
||||
" if opt == 'insert':\n",
|
||||
" cur.execute('INSERT INTO log VALUES (?, ?, ?, ?);', \n",
|
||||
" (foo['Temperature (C)'], foo['Humidity (% rH)'], foo['Photoresistor'], time.time(),)) \n",
|
||||
" elif opt == 'sql':\n",
|
||||
" cur.execute(foo['sql']) \n",
|
||||
" bar = cur.fetchall()\n",
|
||||
" elif opt == 'commit': \n",
|
||||
" con.commit() \n",
|
||||
" bar = 'Database commited'\n",
|
||||
" print('Database commited')\n",
|
||||
" elif opt == 'close': \n",
|
||||
" con.commit()\n",
|
||||
" con.close()\n",
|
||||
" bar = 'Database commited and closed'\n",
|
||||
" print('Database commited and closed')\n",
|
||||
" except Exception as e:\n",
|
||||
" print('sql_exception', e, opt, foo)\n",
|
||||
" pass\n",
|
||||
" q_out.put(bar) \n",
|
||||
" q_out.join()\n",
|
||||
" q_in.task_done()\n",
|
||||
"\n",
|
||||
"q_in, q_out = queue.Queue(), queue.Queue() \n",
|
||||
"threading.Thread(target=database, name='thread-1', daemon=True).start() \n",
|
||||
"\n",
|
||||
"def database_operator(opt_foo): \n",
|
||||
" q_in.join() \n",
|
||||
" q_in.put(opt_foo) \n",
|
||||
" bar = q_out.get() \n",
|
||||
" q_out.task_done() \n",
|
||||
" return bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "e4f22b09",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2022-08-31T07:49:30.202015Z",
|
||||
"start_time": "2022-08-31T07:49:27.088256Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"UTC = dateutil.tz.gettz('UTC') \n",
|
||||
"class HUB:\n",
|
||||
" def __init__(self, temp_ceil = 28.5, lumi_ceil = 650):\n",
|
||||
" self.kasa_ac = kasa.SmartPlug(sec['bedroom_ac_ip']) \n",
|
||||
" self.kasa_bulb = kasa.SmartBulb(sec['bedroom_bulb_ip']) \n",
|
||||
" self.kasa_queue = queue.Queue()\n",
|
||||
" self.params = { 'temp_ceil':temp_ceil,\n",
|
||||
" 'lumi_ceil':lumi_ceil, \n",
|
||||
" 'night_mode':False,\n",
|
||||
" 'manual_mode':False,\n",
|
||||
" 'sunrise_dt':None,\n",
|
||||
" 'sunset_dt' :None, \n",
|
||||
" 'bulb_timer':False # most of the time, bulb_timer is True. \n",
|
||||
" # It is false upon update and test begin. \n",
|
||||
" } \n",
|
||||
" time.sleep(3)\n",
|
||||
" threading.Thread(target=self.kasa_thread).start()\n",
|
||||
" threading.Thread(target=self.update).start() \n",
|
||||
" \n",
|
||||
" async def kasa_worker(self):\n",
|
||||
" while True: \n",
|
||||
" device_name, method_name = self.kasa_queue.get() \n",
|
||||
" device = getattr( self, device_name)\n",
|
||||
" method = getattr(device, method_name)\n",
|
||||
" await method()\n",
|
||||
" self.kasa_queue.task_done()\n",
|
||||
" \n",
|
||||
" def kasa_thread(self):\n",
|
||||
" asyncio.run(self.kasa_worker()) \n",
|
||||
"\n",
|
||||
" def kasa_director(self, device_name, method_name):\n",
|
||||
" #kasa_queue.join()\n",
|
||||
" self.kasa_queue.put((device_name, method_name)) \n",
|
||||
" \n",
|
||||
" def update(self):\n",
|
||||
" lat, lng = (40.7063311, -73.9971931)\n",
|
||||
" onehour = datetime.timedelta(hours=1) \n",
|
||||
" while 1:\n",
|
||||
" print('[Daily Sunrise & Sunset Update]')\n",
|
||||
" date = datetime.datetime.now().strftime('%Y-%m-%d')\n",
|
||||
" r = requests.get(f'https://api.sunrise-sunset.org/json?lat={lat}&lng={lng}&date={date}&formatted=0')\n",
|
||||
" if r.json()['status'] != 'OK': raise\n",
|
||||
" self.params['sunrise_dt'] = datetime.datetime.fromisoformat(r.json()['results']['sunrise'])\n",
|
||||
" self.params['sunset_dt'] = datetime.datetime.fromisoformat(r.json()['results']['sunset']) \n",
|
||||
" while 1: \n",
|
||||
" if self.params['sunrise_dt'].day != datetime.datetime.now().day: \n",
|
||||
" print('A New Day Has Come')\n",
|
||||
" break\n",
|
||||
" self.kasa_director( 'kasa_ac', 'update')\n",
|
||||
" self.kasa_director('kasa_bulb', 'update') \n",
|
||||
" if datetime.datetime.now().astimezone(UTC) < self.params['sunrise_dt'] + onehour or \\\n",
|
||||
" datetime.datetime.now().astimezone(UTC) > self.params['sunset_dt'] - onehour: # Daylight\n",
|
||||
" self.params['night_mode'] = True \n",
|
||||
" else: # At night\n",
|
||||
" self.params['night_mode'] = False\n",
|
||||
" time.sleep(60)\n",
|
||||
" if self.params['bulb_timer']: self.params.update({'bulb_timer':False})\n",
|
||||
"\n",
|
||||
"hub = HUB()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "b3ff53b8",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"start_time": "2022-08-31T07:49:24.905Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"index_html_string = ''' <!DOCTYPE html>\n",
|
||||
"<html>\n",
|
||||
" <head>\n",
|
||||
" <meta charset=\"utf-8\">\n",
|
||||
" <title> hub </title>\n",
|
||||
" <style>\n",
|
||||
" .inp {height: 100px; width: 100px} \n",
|
||||
" \n",
|
||||
" #slider {\n",
|
||||
" -webkit-appearance: none;\n",
|
||||
" width: 100%;\n",
|
||||
" height: 25px;\n",
|
||||
" background: #d3d3d3;\n",
|
||||
" outline: none;\n",
|
||||
" opacity: 0.7;\n",
|
||||
" -webkit-transition: .2s;\n",
|
||||
" transition: opacity .2s;\n",
|
||||
" }\n",
|
||||
" \n",
|
||||
" #slider:hover {\n",
|
||||
" opacity: 1;\n",
|
||||
" } \n",
|
||||
" \n",
|
||||
" #slider::-webkit-slider-thumb {\n",
|
||||
" -webkit-appearance: none;\n",
|
||||
" appearance: none;\n",
|
||||
" width: 100px;\n",
|
||||
" height: 100px;\n",
|
||||
" background: #04AA6D;\n",
|
||||
" cursor: pointer;\n",
|
||||
" }\n",
|
||||
" \n",
|
||||
" #slider::-moz-range-thumb {\n",
|
||||
" width: 100px;\n",
|
||||
" height: 100px;\n",
|
||||
" background: #04AA6D;\n",
|
||||
" cursor: pointer;\n",
|
||||
" } \n",
|
||||
" \n",
|
||||
" td {text-align: center; }\n",
|
||||
" </style>\n",
|
||||
" </head>\n",
|
||||
" <body> \n",
|
||||
" <form method=\"POST\" action=\"/\" enctype=\"multipart/form-data\"> \n",
|
||||
" <table style=\"width: 500px;\" > \n",
|
||||
" <tr>\n",
|
||||
" <td class=\"inp\">Light Mode:</td> \n",
|
||||
" <td style=\"position: relative;\">\n",
|
||||
" <input type=\"radio\" name=\"manual_mode\" value=\"1\" {{'checked' if hub.params['manual_mode'] else ''}} class=\"inp\">\n",
|
||||
" <span style=\"position: absolute;\">Manu</span> \n",
|
||||
" </td> \n",
|
||||
" <td style=\"position: relative;\">\n",
|
||||
" <input type=\"radio\" name=\"manual_mode\" value='0' {{'' if hub.params['manual_mode'] else 'checked'}} class=\"inp\"> \n",
|
||||
" <span style=\"position: absolute; top: 0px; left: 0px; \">Auto</span> \n",
|
||||
" </td> \n",
|
||||
" </tr> \n",
|
||||
" <tr>\n",
|
||||
" <td>Max Celsius Degress:</td>\n",
|
||||
" <td><input type=\"text\" name=\"temp_ceil\" value=\"{{hub.params['temp_ceil']}}\" style=\"font-size: 40px;\" class=\"inp\" id=\"output\"/></td>\n",
|
||||
" <td><input type=\"submit\" value=\"Submit\" class=\"inp\"></td>\n",
|
||||
" </tr> \n",
|
||||
" <tr >\n",
|
||||
" <td colspan=\"3\"><input type=\"range\" min=\"1\" max=\"100\" value=\"{{ 10*hub.params['temp_ceil']-200}}\" style=\"height:100px; width:100%\" class=\"inp\" id=\"slider\"></td>\n",
|
||||
" <script>\n",
|
||||
" var output = document.getElementById(\"output\");\n",
|
||||
" var slider = document.getElementById(\"slider\"); \n",
|
||||
" slider.oninput = function() {\n",
|
||||
" output.setAttribute(\"value\", 20+slider.value/10); \n",
|
||||
" }\n",
|
||||
" </script> \n",
|
||||
" </tr>\n",
|
||||
" <tr> \n",
|
||||
" </tr> \n",
|
||||
" <tr> \n",
|
||||
" <td> <button type=\"button\" onclick=\"light()\" class=\"inp\">Light</button> </td>\n",
|
||||
" <td> <button type=\"button\" class=\"inp\">Placeholder</button> </td>\n",
|
||||
" <td> <button type=\"button\" class=\"inp\">Placeholder</button> </td> \n",
|
||||
" <script>\n",
|
||||
" function light() { \n",
|
||||
" var xmlHttp = new XMLHttpRequest();\n",
|
||||
" xmlHttp.open( \"GET\", \"/remote?pin=15\", false ); \n",
|
||||
" xmlHttp.send( null );\n",
|
||||
" }; \n",
|
||||
" \n",
|
||||
" </script> \n",
|
||||
" </tr> \n",
|
||||
" <tr >\n",
|
||||
" <td colspan=\"3\"> <img src=\"{{sec.cam_1_url}}\"></img> </td> \n",
|
||||
" </tr>\n",
|
||||
" <tr >\n",
|
||||
" <td colspan=\"3\"> <img src=\"{{sec.cam_2_url}}\"></img> </td> \n",
|
||||
" </tr>\n",
|
||||
" \n",
|
||||
" <tr >\n",
|
||||
" <td>EA:DB:84:98:31:F4 </td> <td>MicroPython-9831f4 </td> <td> Controller</td> \n",
|
||||
" </tr>\n",
|
||||
" <tr >\n",
|
||||
" <td>EA:DB:84:9C:54:9E </td> <td>MicroPython-9c549e </td> <td>unknown </td> \n",
|
||||
" </tr>\n",
|
||||
" <tr >\n",
|
||||
" <td>EA:DB:84:9B:90:48 </td> <td>MicroPython-9b9048 </td> <td>HDMI Relay </td> \n",
|
||||
" </tr>\n",
|
||||
" \t\t \n",
|
||||
" \t\t \n",
|
||||
" \t\t \n",
|
||||
" \n",
|
||||
" </table> \n",
|
||||
" <br/> \n",
|
||||
" </form> \n",
|
||||
" </body>\n",
|
||||
"</html> \n",
|
||||
"'''\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"log = logging.getLogger('werkzeug') \n",
|
||||
"log.setLevel(logging.ERROR) \n",
|
||||
"\n",
|
||||
"app = flask.Flask(__name__) \n",
|
||||
"\n",
|
||||
"@app.route(\"/\", methods=['GET', 'POST'])\n",
|
||||
"def index(): \n",
|
||||
" req = flask.request \n",
|
||||
" if req.method == 'GET':\n",
|
||||
" return flask.render_template_string(index_html_string, hub=hub, sec=sec) \n",
|
||||
" elif req.method == 'POST': \n",
|
||||
" hub.params['temp_ceil'] = float(req.form['temp_ceil']) \n",
|
||||
" hub.params['manual_mode'] = int(req.form['manual_mode']) \n",
|
||||
" return flask.redirect(\"/\", code=302)\n",
|
||||
" \n",
|
||||
"@app.route(\"/remote\", methods=['GET'])\n",
|
||||
"def remote(): \n",
|
||||
" pin = flask.request.args.get('pin', -1) \n",
|
||||
" if pin == '13' : \n",
|
||||
" if hub.kasa_ac.is_on: \n",
|
||||
" hub.kasa_director('kasa_ac', 'turn_off')\n",
|
||||
" hub.kasa_director('kasa_ac', 'update')\n",
|
||||
" d = 'A/C Off' \n",
|
||||
" else: \n",
|
||||
" hub.kasa_director('kasa_ac', 'turn_on')\n",
|
||||
" hub.kasa_director('kasa_ac', 'update')\n",
|
||||
" d = 'A/C On' \n",
|
||||
" elif pin == '15' : # \n",
|
||||
" if hub.kasa_bulb.is_on: \n",
|
||||
" hub.kasa_director('kasa_bulb', 'turn_off')\n",
|
||||
" hub.kasa_director('kasa_bulb', 'update')\n",
|
||||
" hub.params['manual_mode'] = True\n",
|
||||
" d = 'Light Off'\n",
|
||||
" else: \n",
|
||||
" hub.kasa_director('kasa_bulb', 'turn_on')\n",
|
||||
" hub.kasa_director('kasa_bulb', 'update') \n",
|
||||
" hub.params['manual_mode'] = False\n",
|
||||
" d = 'Light ON'\n",
|
||||
" return flask.jsonify({'response':d})\n",
|
||||
"\n",
|
||||
"@app.route(\"/log\", methods=['POST'])\n",
|
||||
"def log():\n",
|
||||
" T = flask.request.json['Temperature (C)']\n",
|
||||
" P = flask.request.json['Photoresistor'] \n",
|
||||
" if T > hub.params['temp_ceil'] and hub.kasa_ac.is_on == False: \n",
|
||||
" hub.kasa_director('kasa_ac', 'turn_on')\n",
|
||||
" hub.kasa_director('kasa_ac', 'update') \n",
|
||||
" elif T < hub.params['temp_ceil'] - 1 and hub.kasa_ac.is_on == True: \n",
|
||||
" hub.kasa_director('kasa_ac', 'turn_off')\n",
|
||||
" hub.kasa_director('kasa_ac', 'update') \n",
|
||||
" \n",
|
||||
" if hub.params['manual_mode'] or hub.params['bulb_timer']:\n",
|
||||
" pass \n",
|
||||
" else:\n",
|
||||
" hub.params.update({'bulb_timer':True})\n",
|
||||
" if hub.params['night_mode']: \n",
|
||||
" if P < hub.params['lumi_ceil']: \n",
|
||||
" hub.kasa_director('kasa_bulb', 'turn_on')\n",
|
||||
" hub.kasa_director('kasa_bulb', 'update') \n",
|
||||
" elif hub.kasa_bulb.is_on: \n",
|
||||
" hub.kasa_director('kasa_bulb', 'turn_off')\n",
|
||||
" hub.kasa_director('kasa_bulb', 'update') \n",
|
||||
" else: \n",
|
||||
" hub.kasa_director('kasa_bulb', 'turn_off')\n",
|
||||
" hub.kasa_director('kasa_bulb', 'update') \n",
|
||||
" print(flask.request.json)\n",
|
||||
" database_operator(('insert', flask.request.json)) \n",
|
||||
" return 'OK' \n",
|
||||
"\n",
|
||||
"@app.route(\"/sql\", methods=['POST'])\n",
|
||||
"def sql(): \n",
|
||||
" return {'result':database_operator(('sql', flask.request.json)).__repr__() }\n",
|
||||
" \n",
|
||||
"@app.route(\"/params\", methods=['GET', 'POST'])\n",
|
||||
"def params(): \n",
|
||||
" req = flask.request \n",
|
||||
" if req.method == 'GET':\n",
|
||||
" return hub.params\n",
|
||||
" elif req.method == 'POST': # \n",
|
||||
" hub.params.update(req.json) \n",
|
||||
" return {'return_code':100}\n",
|
||||
"\n",
|
||||
"@app.route('/heartbeat', methods=['GET']) \n",
|
||||
"def heartbeat():\n",
|
||||
" database_operator(('commit', None)) \n",
|
||||
" return 'Cheers!'\n",
|
||||
" \n",
|
||||
"app.run('0.0.0.0','8080')"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.7.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
Reference in New Issue
Block a user