Skip to content

Commit

Permalink
simplify things by setting gateway mac at flash
Browse files Browse the repository at this point in the history
  • Loading branch information
balvig committed Sep 5, 2020
1 parent 8b0e523 commit 9b41840
Show file tree
Hide file tree
Showing 27 changed files with 89 additions and 203 deletions.
55 changes: 30 additions & 25 deletions README.md
Expand Up @@ -30,59 +30,60 @@ vi include/secrets.h
pio run
```

Make a note of the gateway's MAC address:

```bash
Initialized [82:7d:3a:79:14:79]
```

**Note:** Bricks currently requires a WiFi network that uses channel 1.

### 3. Create some bricks

[WIP library here](/examples).
For example a button:
[WIP catalogue here](/examples).
For example a button and an LED:

```bash
export PLATFORMIO_BUILD_FLAGS="'-DBRICKS_GATEWAY_MAC=\"82:7d:3a:79:14:79\"'"

cd examples/button
pio run
```

and an LED:

```bash
cd examples/led
pio run
```

### 4. Scan for bricks
### 4. Communicate with bricks using MQTT

Bricks will announce themselves and their MAC addresses to the gateway when they come online:

```mqtt
bricks/gateway/scan
bricks/in/ee:fa:bc:8e:89:1e/pong: Button
bricks/in/ee:fa:bc:8e:89:8f/pong: LED
```

This will configure all active bricks to use the gateway,
each responding with a "pong" containing their MAC address and name:
You can send messages to the bricks

```mqtt
bricks/in/ee:fa:bc:8e:89:1e/pong: Button
bricks/out/ee:fa:bc:8e:89:8f/setPattern: 1
```

### 5. Connect things in NodeRED

Use the MAC addresses to communicate with the bricks.

Here is a simple example that allows a button brick to control an LED
brick:

<img src=example.png width=500>
<img src=example.gif width=400>

### Todo

- [x] Button
- [ ] LED
- [ ] Try out [Wemos D1 hack](https://www.youtube.com/watch?v=rfPwOtoGO4E)

## Software

### Todo
- [ ] TravisCI
- [ ] Turn "setRotation" into an action instead for LED Matrix
- [ ] Move "ack" to top of stack, run actions in reverse, or split actions
- [ ] Use advertising instead of "scan" to claim bricks

### Nice to haves
- [ ] Fix errors raised by `pio check` (mainly passing `Message` by value)
Expand All @@ -91,10 +92,14 @@ brick:
- [ ] More tests
- [ ] Make aliexpress ble button send notifications
- [ ] Idea: Move sender macAddr into message to reduce params to 1?
- [ ] Use same system for defining mqtt responses (instead of hardcoded "scan")
```
// Connect mqtt event stream
gEvents.init();
gEvents.events[0] = new ScanEvent();
gEvents.events[1] = new BroadcastEvent();
```

## Hardware

### Todo
- [ ] Low profile headers
- [ ] Finish case
- [ ] Nicer stickers
- [ ] Button
- [ ] LED
- [ ] Try out [Wemos D1 hack](https://www.youtube.com/watch?v=rfPwOtoGO4E)

16 changes: 8 additions & 8 deletions examples/README.md
@@ -1,8 +1,7 @@
# Brick Examples

- [Gateway](gateway)
- [Button (realtime)](button)
- [Button (sleeps)](button-sleep)
- [Button](button)
- [LED](led)
- [LED RGB](led-rgb)
- [LED 8x8 Matrix](led-matrix)
Expand All @@ -14,12 +13,13 @@

### Inbox

| key | description | values |
|------------|-------------------------------------------|----------------------|
| * | Responds with `ack:<KEY>` to all messages | |
| ping | Saves gateway MAC, responds with `pong` | |
| sleep | Sleep for `value` seconds | 0 (forever), 1-13612 |
| getBattery | Ask to send battery value | |
| key | description | values |
|------------|---------------------------------------------------------------------------|----------------------|
| * | Responds with `ack:<KEY>` to all messages | |
| ping | Saves gateway MAC, responds with `pong` | |
| sleep | Sleep for `value` seconds | 0 (forever), 1-13612 |
| getBattery | Ask to send battery value | |
| setOta | Allows `pio run -t upload --upload-port 192.168.4.1` when connected to AP | |

### Outbox

Expand Down
2 changes: 1 addition & 1 deletion examples/ble/src/main.cpp
Expand Up @@ -8,7 +8,7 @@ using namespace Bricks;
#include <NimBLEDevice.h>

BLEScan *pBLEScan;
const int8_t MINIMUM_RSSI = -70;
const int8_t MINIMUM_RSSI = -80;

class BLECallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice* device) {
Expand Down
4 changes: 0 additions & 4 deletions examples/button-sleep/README.md

This file was deleted.

9 changes: 0 additions & 9 deletions examples/button-sleep/platformio.ini

This file was deleted.

21 changes: 0 additions & 21 deletions examples/button-sleep/src/main.cpp

This file was deleted.

4 changes: 2 additions & 2 deletions examples/button/README.md
@@ -1,7 +1,7 @@
# Button

"Always on" button.
Very responsive but will consume battery/should probably be plugged in.
If plugged in can use `pressed/release` messages.
Can also be put to sleep and use RST wake-up as trigger.

## Outbox

Expand Down
2 changes: 1 addition & 1 deletion examples/button/src/main.cpp
Expand Up @@ -23,7 +23,7 @@ void setup() {
gBrick.init();

// Configure inbox
gInbox.init("Button (Realtime)");
gInbox.init("Button");
}

void loop() {
Expand Down
1 change: 1 addition & 0 deletions examples/gateway/platformio.ini
Expand Up @@ -6,6 +6,7 @@ extra_configs =
[env]
build_flags=
-include include/secrets.h
-DBRICKS_GATEWAY_MAC=\"00:00:00:00:00:00\"
lib_extra_dirs = ../../
lib_deps =
${common.lib_deps}
Expand Down
1 change: 0 additions & 1 deletion library.json
Expand Up @@ -8,7 +8,6 @@
},
"dependencies": {
"ArduinoLog": "~1.0.3",
"EEPROM": ">0",
"PubSubClient": "~2.8",
"WifiEspNow": "~0.0.20190814"
},
Expand Down
1 change: 0 additions & 1 deletion shared.ini
Expand Up @@ -2,7 +2,6 @@
[common]
lib_deps =
ArduinoLog
EEPROM
PubSubClient
WifiEspNow

Expand Down
19 changes: 16 additions & 3 deletions src/Bricks.Brick.cpp
Expand Up @@ -4,17 +4,30 @@ namespace Bricks {
void Brick::init(const WiFiMode_t wifiMode) {
// Configure Wi-Fi
WiFi.mode(wifiMode);
WiFi.softAP("ESPNOW", NULL, BRICKS_WIFI_CHANNEL, true); // hide AP

// Connect ESPNOW
if (WifiEspNow.begin()) {
String macStr = WiFi.softAPmacAddress();
macStr.toLowerCase();
Log.notice("ESPN: Initialized [%s]" CR, macStr.c_str());
logMac(wifiMode);
}
else {
Log.error("ESPN: Error initializing" CR);
}
}

void Brick::logMac(WiFiMode_t wifiMode) {
String macStr;

if(wifiMode == WIFI_STA) {
macStr = WiFi.macAddress();
}
else {
macStr = WiFi.softAPmacAddress();
}

macStr.toLowerCase();
Log.notice("ESPN: Initialized [%s]" CR, macStr.c_str());
}

Brick gBrick = Brick();
}
6 changes: 5 additions & 1 deletion src/Bricks.Brick.h
Expand Up @@ -9,10 +9,14 @@
#endif
#include <WifiEspNow.h>

#include <Bricks.Constants.h>

namespace Bricks {
class Brick {
public:
void init(const WiFiMode_t wifiMode = WIFI_AP);
void init(const WiFiMode_t wifiMode = WIFI_AP); // AP is more stable that STA when communication with AT_STA
private:
void logMac(WiFiMode_t wifiMode);
};

extern Brick gBrick;
Expand Down
3 changes: 0 additions & 3 deletions src/Bricks.Constants.h
Expand Up @@ -2,12 +2,9 @@
#define BRICKS_CONSTANTS_H

#define BRICKS_WIFI_CHANNEL 1
#define BRICKS_NAME_PREFIX "Brick - "
#define BRICKS_PING_ACTION "ping"
#define MAC_FORMAT "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx"
#define MAC_ADDR_SIZE 6
#define MAC_STR_SIZE 18
#define MAC_UNSET {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
#define MICROSECONDS 1000000
#define KEY_SIZE 20

Expand Down
30 changes: 4 additions & 26 deletions src/Bricks.Events.cpp
Expand Up @@ -46,15 +46,10 @@ namespace Bricks {
char *value = (char *) bytes;
Log.trace("MQTT: <- %s: %s" CR, topic, value);

if(strcmp(BRICKS_MESSAGES_SCAN, topic) == 0) {
scanForBricks();
}
else {
uint8_t macAddr[MAC_ADDR_SIZE];
char key[KEY_SIZE];
parseTopic(topic, macAddr, key);
gOutbox.send(macAddr, key, value);
}
uint8_t macAddr[MAC_ADDR_SIZE];
char key[KEY_SIZE];
parseTopic(topic, macAddr, key);
gOutbox.send(macAddr, key, value);
}

void Events::parseTopic(const char *topic, uint8_t *macAddr, char *key) {
Expand Down Expand Up @@ -83,7 +78,6 @@ namespace Bricks {
if(mqtt.connect(BRICKS_MQTT_CLIENT, BRICKS_MQTT_USER, BRICKS_MQTT_PASSWORD)) {
Log.notice("MQTT: Connected" CR);
subscribe(BRICKS_MESSAGES_OUT "/#");
subscribe(BRICKS_MESSAGES_SCAN);
}
else {
Log.warning("MQTT: Failed [%s]. Retrying in 5 secs" CR, mqtt.state());
Expand All @@ -97,21 +91,5 @@ namespace Bricks {
Log.trace("MQTT: Subscribed [%s]" CR, topic);
}

void Events::scanForBricks() {
Log.notice("WIFI: Scanning for Bricks" CR);
const uint8_t scanResults = WiFi.scanNetworks();

for(int i = 0; i < scanResults; ++i) {
if(WiFi.SSID(i).indexOf(BRICKS_NAME_PREFIX) == 0) {
Log.trace("WIFI: Brick found on channel %d" CR, WiFi.channel(i));
gOutbox.send(WiFi.BSSID(i), BRICKS_PING_ACTION);
}
}

WiFi.scanDelete();
Log.notice("WIFI: Scan complete" CR);
gEvents.publish(BRICKS_MESSAGES_SCAN "/done");
}

Events gEvents = Events();
}
2 changes: 0 additions & 2 deletions src/Bricks.Events.h
Expand Up @@ -27,7 +27,6 @@

#define BRICKS_MESSAGES_IN BRICKS_MQTT_TOPIC_PREFIX "/in"
#define BRICKS_MESSAGES_OUT BRICKS_MQTT_TOPIC_PREFIX "/out"
#define BRICKS_MESSAGES_SCAN BRICKS_MQTT_TOPIC_PREFIX "/gateway/scan"

namespace Bricks {
class Events {
Expand All @@ -48,7 +47,6 @@ namespace Bricks {
void connectWiFi();
void connectMQTT();
void subscribe(const char *topic);
static void scanForBricks();
};

extern Events gEvents;
Expand Down
7 changes: 3 additions & 4 deletions src/Bricks.Inbox.cpp
Expand Up @@ -2,10 +2,9 @@

namespace Bricks {
void Inbox::init(const char *name) {
actions[3] = new OtaAction();
actions[4] = new ListAction();
actions[5] = new PongAction(name);
actions[6] = new StoreGatewayAction();
actions[4] = new OtaAction();
actions[5] = new ListAction();
actions[6] = new PongAction(name);
actions[7] = new SleepAction();
actions[8] = new BatteryAction();
actions[9] = new AckAction();
Expand Down
1 change: 0 additions & 1 deletion src/Bricks.Inbox.h
Expand Up @@ -16,7 +16,6 @@
#include <Bricks.OtaAction.h>
#include <Bricks.PongAction.h>
#include <Bricks.SleepAction.h>
#include <Bricks.StoreGatewayAction.h>

# define MAX_ACTIONS 10

Expand Down
7 changes: 6 additions & 1 deletion src/Bricks.OtaAction.cpp
Expand Up @@ -10,7 +10,7 @@ namespace Bricks {

void OtaAction::callback(const uint8_t *macAddr, const Message message) {
initOta();
gOutbox.send(macAddr, "ota", WiFi.softAPIP().toString().c_str());
startAP();
}

void OtaAction::initOta() {
Expand Down Expand Up @@ -42,4 +42,9 @@ namespace Bricks {
});
ArduinoOTA.begin();
}

void OtaAction::startAP() {
WiFi.mode(WIFI_AP);
WiFi.softAP("Brick - OTA", NULL, BRICKS_WIFI_CHANNEL);
}
}
1 change: 1 addition & 0 deletions src/Bricks.OtaAction.h
Expand Up @@ -14,6 +14,7 @@ namespace Bricks {
void callback(const uint8_t *macAddr, const Message message);
private:
void initOta();
void startAP();
};
}
#endif

0 comments on commit 9b41840

Please sign in to comment.