オッス!オラ在宅
リモワしているとポモドーロ・テクニックみたいなちょっとした息抜きをし辛くないですか?もしくは家族の容赦ない割り込みと上司の定める離席ルールって相容れないですよね。
席に座ってるのが見えてれば良い?それ、IoTでなんとかできます。
いっちょやってみっか!
材料です。
- ESP32とかArduino系マイコン
- HC-SR04など距離測定デバイス
- Webカメラなど自分の仕事姿を撮影できるデバイス
- 動画を再生するディスプレイ
ワクワクすっぞ!
一定時間離席すると自動でキー入力してくれる仮想キーボードデバイスです
最初にWebカメラで仕事してる動画を撮影してください。改行キーでループ再生するように設定してください。
コードをESP32に書き込んで距離センシングを組み立てます
デバイスをBluetoothでペアリングします。
上司がこちらを見てない隙に仕事中動画にWebカメラをセットします。なあにポテチ袋に液晶テレビ仕込むより簡単ですよ!
離席しましょう。5秒カウントすると動画が再生されます。
上司に「全力コーディング集中します。反応が遅いかもしれません。」とでもメッセージを入れてあげるとなお効果的でしょう。w
コード
zuruiot.ino
# include <BLEDevice.h>
# include <BLEUtils.h>
# include <BLEServer.h>
# include "BLE2902.h"
# include "BLEHIDDevice.h"
# include "HIDTypes.h"
# include "HIDKeyboardTypes.h"
BLEHIDDevice* hid;
BLECharacteristic* input;
BLECharacteristic* output;
uint8_t buttons = 0;
uint8_t button1 = 0;
uint8_t button2 = 0;
uint8_t button3 = 0;
bool connected = false;
# define Trigger_Pin 17
# define Echo_Pin 16
int V = 340; //音速
int dest = 50; //何センチ以下でカウンターを下げるか
boolean enterFlag = false; //在席・離席フラグ
int enterCounter = 5; // 何回閾値以下になったら改行を押すか
class MyCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* pServer){
connected = true;
BLE2902* desc = (BLE2902*)input->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
desc->setNotifications(true);
}
void onDisconnect(BLEServer* pServer) {
connected = false;
BLE2902* desc = (BLE2902*)input->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
desc->setNotifications(false);
}
};
class MyOutputCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic* me){
uint8_t* value = (uint8_t*)(me->getValue().c_str());
ESP_LOGI(LOG_TAG, "special keys: %d", *value);
}
};
void taskServer(void*){
BLEDevice::init("ZuruIoT");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyCallbacks());
hid = new BLEHIDDevice(pServer);
input = hid->inputReport(1); // <-- input REPORTID from report map
output = hid->outputReport(1); // <-- output REPORTID from report map
output->setCallbacks(new MyOutputCallbacks());
std::string name = "ElectronicCats";
hid->manufacturer()->setValue(name);
hid->pnp(0x02, 0xe502, 0xa111, 0x0210);
hid->hidInfo(0x00,0x02);
BLESecurity *pSecurity = new BLESecurity();
//pSecurity->setKeySize();
pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND);
const uint8_t report[] = {
USAGE_PAGE(1), 0x01, // Generic Desktop Ctrls
USAGE(1), 0x06, // Keyboard
COLLECTION(1), 0x01, // Application
REPORT_ID(1), 0x01, // Report ID (1)
USAGE_PAGE(1), 0x07, // Kbrd/Keypad
USAGE_MINIMUM(1), 0xE0,
USAGE_MAXIMUM(1), 0xE7,
LOGICAL_MINIMUM(1), 0x00,
LOGICAL_MAXIMUM(1), 0x01,
REPORT_SIZE(1), 0x01, // 1 byte (Modifier)
REPORT_COUNT(1), 0x08,
HIDINPUT(1), 0x02, // Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position
REPORT_COUNT(1), 0x01, // 1 byte (Reserved)
REPORT_SIZE(1), 0x08,
HIDINPUT(1), 0x01, // Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position
REPORT_COUNT(1), 0x06, // 6 bytes (Keys)
REPORT_SIZE(1), 0x08,
LOGICAL_MINIMUM(1), 0x00,
LOGICAL_MAXIMUM(1), 0x65, // 101 keys
USAGE_MINIMUM(1), 0x00,
USAGE_MAXIMUM(1), 0x65,
HIDINPUT(1), 0x00, // Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position
REPORT_COUNT(1), 0x05, // 5 bits (Num lock, Caps lock, Scroll lock, Compose, Kana)
REPORT_SIZE(1), 0x01,
USAGE_PAGE(1), 0x08, // LEDs
USAGE_MINIMUM(1), 0x01, // Num Lock
USAGE_MAXIMUM(1), 0x05, // Kana
HIDOUTPUT(1), 0x02, // Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile
REPORT_COUNT(1), 0x01, // 3 bits (Padding)
REPORT_SIZE(1), 0x03,
HIDOUTPUT(1), 0x01, // Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile
END_COLLECTION(0)
};
hid->reportMap((uint8_t*)report, sizeof(report));
hid->startServices();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->setAppearance(HID_KEYBOARD);
pAdvertising->addServiceUUID(hid->hidService()->getUUID());
pAdvertising->start();
hid->setBatteryLevel(7);
ESP_LOGD(LOG_TAG, "Advertising started!");
delay(portMAX_DELAY);
};
void setup() {
Serial.begin(115200);
pinMode(Trigger_Pin, OUTPUT);
pinMode(Echo_Pin, INPUT);
digitalWrite(Trigger_Pin, LOW);
xTaskCreate(taskServer, "server", 20000, NULL, 5, NULL);
}
void sendTrigger() {
digitalWrite(Trigger_Pin,HIGH);
delayMicroseconds(10);
digitalWrite(Trigger_Pin, LOW);
}
void enterPress() {
vTaskDelay(1000);
const char* hello = "\n";
while(*hello) {
KEYMAP map = keymap[(uint8_t)*hello];
Serial.println(buttons);
uint8_t msg[] = {map.modifier || buttons, 0x0, map.usage, 0x0,0x0,0x0,0x0,0x0};
input->setValue(msg,sizeof(msg));
input->notify();
hello++;
uint8_t msg1[] = {0x0, 0x0, 0x0, 0x0,0x0,0x0,0x0,0x0};
input->setValue(msg1,sizeof(msg1));
input->notify();
delay(10);
}
xTaskCreate(taskServer, "server", 20000, NULL, 5, NULL);
}
void loop() {
sendTrigger();
while(!digitalRead(Echo_Pin)){ }
unsigned long t1 = micros();
while(digitalRead(Echo_Pin)){ }
unsigned long t2 = micros();
unsigned long t = t2 - t1;
int dis = V * t /20000;
Serial.print(dis);
Serial.println("cm");
if (enterFlag == false) {
if (dis > dest) {
enterCounter--;
Serial.println("RISEKI!");
Serial.println(enterCounter);
if (enterCounter < 0) {
enterPress();
enterCounter = 5;
enterFlag = true;
}
} else {
enterCounter = 5;
}
} else {
if (dis < dest) {
enterCounter--;
Serial.println("ZAISEKI!");
Serial.println(enterCounter);
if (enterCounter < 0) {
enterPress();
enterCounter = 5;
enterFlag = false;
}
} else {
enterCounter = 5;
}
}
delay(1000);
}
もうちょっとだけ続くんじゃ
え!?
離席検出がデプスカメラ対応だって!?そんなあ・・・
ま、3時間くらいで作ったジョークプログラムってことで!!w
FYI
- 距離センサーの使い方の参考に
- BLEキーボードの実装の参考に