Compare commits
No commits in common. "5e1bdac09e0bfc9fa649e6e3ab0c2f6c1dc80b7f" and "52d7c9e9a106cf553269cb07a7c94dc7529815d0" have entirely different histories.
5e1bdac09e
...
52d7c9e9a1
@ -4,10 +4,12 @@
|
||||
#include <NTPClient.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include "certificate.h"
|
||||
#include "secret.h"
|
||||
#include "secrets.h"
|
||||
|
||||
#define CERT mqtt_broker_cert
|
||||
#define MSG_BUFFER_SIZE (50)
|
||||
|
||||
|
||||
const char* ssid = VITRINE_SSID;
|
||||
const char* password = VITRINE_WIFI_PASS;
|
||||
const char* mqtt_server = "mqtt.klank.school"; // eg. your-demo.cedalo.cloud or 192.168.1.11
|
||||
@ -15,106 +17,60 @@ const uint16_t mqtt_server_port = 7000; // or 8883 most common for tls t
|
||||
const char* mqttUser = MQTT_ARDUINO_USERNAME;
|
||||
const char* mqttPassword = MQTT_ARDUINO_PASS;
|
||||
|
||||
#define MAIN_CHANNEL "main/#"
|
||||
bool isOn = false;
|
||||
|
||||
#define MAIN_CHANNEL "main"
|
||||
|
||||
|
||||
#define RELAY_1 1
|
||||
//--------------------------------------
|
||||
// globals
|
||||
//--------------------------------------
|
||||
#ifdef MQTT_TLS
|
||||
WiFiClientSecure wifiClient;
|
||||
#else
|
||||
WiFiClient wifiClient;
|
||||
#endif
|
||||
WiFiUDP ntpUDP;
|
||||
NTPClient timeClient(ntpUDP);
|
||||
PubSubClient mqttClient(wifiClient);
|
||||
|
||||
#if hasRelayShield
|
||||
const int RELAY_PIN_FAN1 = 1;
|
||||
const int RELAY_PIN_FAN2 = 2;
|
||||
const int RELAY_PIN_RADIO1 = 3;
|
||||
const int RELAY_PIN_LAMP1 = 4;
|
||||
const int RELAY_PIN_LAMP2 = 5;
|
||||
// const int RELAY_PIN = 6;
|
||||
// const int RELAY_PIN = 7;
|
||||
// const int RELAY_PIN = 8;
|
||||
#endif
|
||||
|
||||
#if hasMotorshield
|
||||
#include <Adafruit_MotorShield.h>
|
||||
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
|
||||
Adafruit_DCMotor* motor1 = AFMS.getMotor(1);
|
||||
Adafruit_DCMotor* motor2 = AFMS.getMotor(2);
|
||||
Adafruit_DCMotor* motor3 = AFMS.getMotor(3);
|
||||
Adafruit_DCMotor* motor4 = AFMS.getMotor(4);
|
||||
void setup_wifi() {
|
||||
|
||||
void movePrinter(String topic, int payload) {
|
||||
|
||||
if (topic.indexOf("speed") > 0) {
|
||||
if (topic.indexOf("printer/one") > 0) {
|
||||
motor1->setSpeed(payload);
|
||||
} else if (topic.indexOf("printer/two") > 0) {
|
||||
motor2->setSpeed(payload);
|
||||
} else if (topic.indexOf("printer/three") > 0) {
|
||||
motor3->setSpeed(payload);
|
||||
} else if (topic.indexOf("printer/four") > 0) {
|
||||
motor4->setSpeed(payload);
|
||||
}
|
||||
} else {
|
||||
if (payload == 0) {
|
||||
payload = 4;
|
||||
}
|
||||
|
||||
if (topic.indexOf("printer/one") > 0) {
|
||||
motor1->run(payload);
|
||||
} else if (topic.indexOf("printer/two") > 0) {
|
||||
motor2->run(payload);
|
||||
} else if (topic.indexOf("printer/three") > 0) {
|
||||
motor3->run(payload);
|
||||
} else if (topic.indexOf("printer/four") > 0) {
|
||||
motor4->run(payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if hasRelayShield
|
||||
void togglePower(int pin, int payload) {
|
||||
bool state = false;
|
||||
if (payload > 1) {
|
||||
state = true;
|
||||
}
|
||||
|
||||
digitalWrite(pin, state);
|
||||
delay(500);
|
||||
}
|
||||
#endif
|
||||
|
||||
void callback(char* topic, uint8_t* payload, unsigned int length) {
|
||||
String t(topic);
|
||||
delay(10);
|
||||
Serial.println();
|
||||
Serial.print("Connecting to ");
|
||||
Serial.println(ssid);
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
Serial.println("start while");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(50);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("i am here 1");
|
||||
timeClient.begin();
|
||||
|
||||
Serial.println("WiFi connected");
|
||||
}
|
||||
|
||||
void callback(char* topic, byte* payload, unsigned int length) {
|
||||
Serial.print("Message arrived on topic: '");
|
||||
Serial.print(topic);
|
||||
Serial.print("' with payload: ");
|
||||
String message = "";
|
||||
|
||||
for (unsigned int i = 0; i < length; i++) {
|
||||
message += (char)payload[i];
|
||||
Serial.print((char)payload[i]);
|
||||
}
|
||||
Serial.println(message);
|
||||
|
||||
#if hasMotorshield
|
||||
if (t.indexOf("/printer/") > 0) {
|
||||
movePrinter(t, message.toInt());
|
||||
if (isOn) {
|
||||
digitalWrite(RELAY_1, HIGH);
|
||||
isOn = false;
|
||||
} else {
|
||||
digitalWrite(RELAY_1, LOW);
|
||||
isOn = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if hasRelayShield
|
||||
if (t.indexOf("/fan/one") > 0) {
|
||||
togglePower(RELAY_PIN_FAN1, message.toInt());
|
||||
} else if (t.indexOf("/fan/two") > 0) {
|
||||
togglePower(RELAY_PIN_FAN2, message.toInt());
|
||||
} else if (t.indexOf("/radio/one") > 0) {
|
||||
togglePower(RELAY_PIN_RADIO1, message.toInt());
|
||||
} else if (t.indexOf("/lamp/one") > 0) {
|
||||
togglePower(RELAY_PIN_LAMP1, message.toInt());
|
||||
} else if (t.indexOf("/lamp/two") > 0) {
|
||||
togglePower(RELAY_PIN_LAMP2, message.toInt());
|
||||
}
|
||||
#endif
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
@ -122,13 +78,12 @@ void connect() {
|
||||
while (!mqttClient.connected()) {
|
||||
|
||||
Serial.print("Attempting MQTT connection...");
|
||||
String clientId = arduinoName;
|
||||
|
||||
String clientId = "ESP8266Client-";
|
||||
clientId += String(random(0xffff), HEX);
|
||||
if (mqttClient.connect(clientId.c_str(), mqttUser, mqttPassword)) {
|
||||
Serial.println("connected");
|
||||
mqttClient.subscribe(MAIN_CHANNEL);
|
||||
mqttClient.publish("main/hello", ("A wild arduino appeared"));
|
||||
mqttClient.publish(MAIN_CHANNEL, ("Whaddup can i stay? "));
|
||||
} else {
|
||||
Serial.print("failed, rc=");
|
||||
Serial.print(mqttClient.state());
|
||||
@ -138,50 +93,15 @@ void connect() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.begin(9600);
|
||||
Serial.println("run setup");
|
||||
Serial.print("Connecting to ");
|
||||
Serial.println(ssid);
|
||||
|
||||
#if hasRelayShield
|
||||
pinMode(RELAY_PIN_FAN1, OUTPUT);
|
||||
pinMode(RELAY_PIN_FAN2, OUTPUT);
|
||||
pinMode(RELAY_PIN_RADIO1, OUTPUT);
|
||||
pinMode(RELAY_PIN_LAMP1, OUTPUT);
|
||||
pinMode(RELAY_PIN_LAMP2, OUTPUT);
|
||||
#endif
|
||||
|
||||
#if hasMotorshield
|
||||
Serial.println("i have a motorshield");
|
||||
if (!AFMS.begin()) {
|
||||
Serial.println("Could not find Motor Shield. Check wiring.");
|
||||
while (1)
|
||||
;
|
||||
};
|
||||
|
||||
motor1->setSpeed(160);
|
||||
motor1->run(RELEASE);
|
||||
motor2->setSpeed(160);
|
||||
motor2->run(RELEASE);
|
||||
motor3->setSpeed(160);
|
||||
motor3->run(RELEASE);
|
||||
motor4->setSpeed(160);
|
||||
motor4->run(RELEASE);
|
||||
#endif
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(50);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("----");
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("----");
|
||||
|
||||
timeClient.begin();
|
||||
setup_wifi();
|
||||
Serial.println("finish setup_wifi");
|
||||
pinMode(RELAY_1, OUTPUT);
|
||||
|
||||
mqttClient.setServer(mqtt_server, mqtt_server_port);
|
||||
mqttClient.setCallback(callback);
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
# Running the Arduino side
|
||||
The arduino listens to MQTT messages, and acts accordingly. Each arduino can serve a different purpose, for instance, running motor shields, or turning a fan on/off.
|
||||
|
||||
|
||||
|
||||
### 1. Create your own "secret.h" file, following this format
|
||||
|
||||
```C++
|
||||
#define VITRINE_SSID "";
|
||||
#define VITRINE_WIFI_PASS ""
|
||||
#define MQTT_ARDUINO_USERNAME ""
|
||||
#define MQTT_ARDUINO_PASS ""
|
||||
```
|
||||
|
||||
### 2. Select your board to compile with. As I always forget which boards to select, here's my cheat sheet:
|
||||
|
||||
| Arduino | Board |
|
||||
| ------------- | ------------- |
|
||||
| ArduinoWifi | LOLIN(WeMos) D1 R1 |
|
||||
| ... | ... |
|
||||
|
||||
### 3. Do something with the make files
|
||||
|
||||
arduino-cli compile -b arduino:avr:uno --build-property "build.extra_flags=\"-DMY_DEFINE=\"hello world\"\"" /home/user/Arduino/MySketch
|
@ -1,45 +0,0 @@
|
||||
|
||||
rules = {
|
||||
"main/fan/one": [
|
||||
{ # after the fan has been on 2 times, another fan should be turned on
|
||||
"count": 2, # the amount of times
|
||||
"state": "on", # it has had this state
|
||||
"doTopic": "main/fan/two", # i will send to topic
|
||||
"doMessage": "on", # this message
|
||||
"delay": False, # after this amount of seconds
|
||||
"reset": True, # and i should reset my count afterwards
|
||||
},
|
||||
{ # After the fan is turned off, the next fan should be turned on
|
||||
"count": 4, # the amount of times
|
||||
"state": "off", # it has had this state
|
||||
"doTopic": "main/fan/two", # i will send to topic
|
||||
"doMessage": "on", # this message
|
||||
"delay": 4, # after this amount of seconds
|
||||
"reset": True, # and i should reset my count afterwards
|
||||
},
|
||||
{ # Turn the fan off every time after 1 minute
|
||||
"count": False, # the amount of times. If its false, just do it.
|
||||
"state": "on", # it has had this state
|
||||
"doTopic": "main/fan/one", # i will send to topic
|
||||
"doMessage": "off", # this message
|
||||
"delay": 4, # after this amount of seconds
|
||||
"reset": False, # and i should reset my count afterwards
|
||||
},
|
||||
{ # Turn the fan on every time after 6 minute
|
||||
"count": 3, # the amount of times. If its false, just do it.
|
||||
"state": "on", # it has had this state
|
||||
"doTopic": "main/fan/one", # i will send to topic
|
||||
"doMessage": "off", # this message
|
||||
"delay": 360, # after this amount of seconds
|
||||
"reset": False, # and i should reset my count afterwards
|
||||
},
|
||||
{ # Every 5 minutes, do gesture X
|
||||
"count": 1,
|
||||
"state": "on",
|
||||
"doTopic": "gesture/fan/one",
|
||||
"doMessage": "on",
|
||||
"delay": 5 * 60,
|
||||
"reset": True
|
||||
}
|
||||
]
|
||||
}
|
12
rule-listener/rules.py
Normal file
12
rule-listener/rules.py
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"main/fan/1": [
|
||||
{ # after the fan has been on 2 times, another fan should be turned on
|
||||
"count": 2, # the amount of times
|
||||
"state": "on", # it has had this state
|
||||
"doTopic": "main/fan/2", # i will send to topic
|
||||
"doMessage": "on", # this message
|
||||
"delay": 3, # after this amount of seconds
|
||||
"reset": True # and i should reset my count afterwards
|
||||
}
|
||||
]
|
||||
}
|
@ -1,46 +1,23 @@
|
||||
import paho.mqtt.client as mqtt
|
||||
import asyncio
|
||||
import secrets
|
||||
import data
|
||||
from random import randrange
|
||||
|
||||
import rules
|
||||
|
||||
state = {}
|
||||
rules = data.rules
|
||||
|
||||
mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
||||
|
||||
async def on_gesture_message():
|
||||
state = False
|
||||
delay = 3
|
||||
for i in range(randrange(4,8)):
|
||||
await asyncio.sleep(delay)
|
||||
delay = delay * 0.7
|
||||
if state:
|
||||
print("do left")
|
||||
state = False
|
||||
else:
|
||||
print("do right")
|
||||
state = True
|
||||
|
||||
print("done")
|
||||
|
||||
|
||||
|
||||
def on_connect(client, userdata, flags, reason_code, properties):
|
||||
print(f"Connected with result code {reason_code}")
|
||||
client.subscribe("main/#")
|
||||
mqttc.message_callback_add("gesture/#", on_gesture_message)
|
||||
|
||||
client.subscribe("gesture/#")
|
||||
|
||||
async def publish_later(rule):
|
||||
print(f"publish_later: Processing message with doTopic {rule['doTopic']} after {rule['delay']} seconds delay")
|
||||
await asyncio.sleep(rule['delay'])
|
||||
del rule['doingDelay']
|
||||
publish(rule['doTopic'], rule['doMessage'])
|
||||
async def publish_later(topic, msg, delay):
|
||||
print(f"publish_later: Processing message with topic {topic} after {delay} seconds delay")
|
||||
await asyncio.sleep(delay)
|
||||
print(f"publish_later: completed delay")
|
||||
publish(topic, msg)
|
||||
|
||||
def publish(topic, msg):
|
||||
print(f"publish {topic} {msg}")
|
||||
result = mqttc.publish(topic, msg)
|
||||
|
||||
status = result[0]
|
||||
@ -50,49 +27,34 @@ def publish(topic, msg):
|
||||
|
||||
def check_against_rules(msg):
|
||||
if msg.topic in rules:
|
||||
print(f"Found {len(rules[msg.topic])} rules on this topic"),
|
||||
|
||||
willReset = False
|
||||
|
||||
print(f"... ... Found {len(rules[msg.topic])} rules on this topic")
|
||||
for rule in rules[msg.topic]:
|
||||
print(f"Rule: when the count is > {rule['count']}. Current = {state[msg.topic]['count'][msg.payload]} on payload {msg.payload}"),
|
||||
|
||||
if (state[msg.topic]['count'][msg.payload] >= rule['count'] or rule['count'] == False) and msg.payload == rule['state']:
|
||||
print(f"... ... Rule is met when the count is above {rule['count']}. Current count is {state[msg.topic]['count']}")
|
||||
|
||||
if state[msg.topic]['count'] > rule['count']:
|
||||
if(rule['reset']):
|
||||
willReset = True
|
||||
state[msg.topic]['count'] = 0
|
||||
|
||||
if rule['delay']:
|
||||
if not 'doingDelay' in rule:
|
||||
rule['doingDelay'] = True
|
||||
asyncio.run_coroutine_threadsafe(publish_later(rule), loop)
|
||||
else:
|
||||
print('not scheduling')
|
||||
asyncio.run_coroutine_threadsafe(publish_later(rule['doTopic'], rule['doMessage'], rule['delay']), loop)
|
||||
else:
|
||||
publish(rule['doTopic'], rule['doMessage'])
|
||||
|
||||
if willReset:
|
||||
state[msg.topic]['count'][msg.payload] = 0
|
||||
|
||||
else:
|
||||
print("... ... i have no rules for this topic")
|
||||
|
||||
# The callback for when a PUBLISH message is received from the server.
|
||||
def on_message(client, userdata, msg):
|
||||
print("on message")
|
||||
print("on_message")
|
||||
if msg.retain:
|
||||
return False
|
||||
|
||||
if msg.topic in state:
|
||||
state[msg.topic]["count"] += 1
|
||||
else:
|
||||
msg.payload = str(msg.payload.decode("utf-8"))
|
||||
|
||||
if len(msg.payload) > 140:
|
||||
print("way to long of a message, not gonna store that")
|
||||
return False
|
||||
|
||||
if msg.topic not in state:
|
||||
state[msg.topic] = {'count': {}}
|
||||
|
||||
state[msg.topic]['count'].setdefault(msg.payload, 0)
|
||||
state[msg.topic]['count'][msg.payload] += 1
|
||||
check_against_rules(msg)
|
||||
state[msg.topic] = {}
|
||||
state[msg.topic]["count"] = 0
|
||||
|
||||
check_against_rules(msg)
|
||||
|
||||
async def main():
|
||||
global loop
|
||||
@ -107,7 +69,7 @@ async def main():
|
||||
|
||||
# Start the MQTT loop in a background thread
|
||||
mqttc.loop_start()
|
||||
|
||||
|
||||
# Keep the asyncio event loop running
|
||||
await asyncio.Event().wait()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user