Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
3
Help us understand the problem. What is going on with this article?
@MikH

LINE Thingsのアイデアを考え中

More than 1 year has passed since last update.

LINE Thingsを面白く使ってみたい

LINE Things は LINE 上から利用できる、新しい IoT プラットフォームです。Bluetooth LE を利用して、IoT デバイスに接続し、LIFF や LINE Bot からコミュニケーションができるようになります。
LINE Thingsを面白く使ってみたいですね。

LINE Thingsならではの場面を考えた

Wifiでもなく、LTEでもなく、Bluetooth LE でLINE通信する特徴を生かしたものは何かを考えました。
デバイスは、多人数の人が使うものでなく、個人持ちのデバイスに向いている。
使う場所は、Wifiがない場所で使うことで、他のデバイスとの差別化が図れる。

LINE Thingsの用途を考えた。

「外出している時に、個人持ちのデバイス」に絞り用途を考えた。

  • アイデア1:車の運転中。ワイパーでデバイスが反応して、LINE Botがいいことしてくれる。眠気を覚ましたり、簡単なゲームをしたり。運転中によそ見をせずに簡単に届くスイッチとして。

  • アイデア2:ゴルフ。スコアカウンターとして使用。スコアが悪いときにLINE Botが慰めてくれたり、スコアを合計してくれたりする。一緒にプレイしているメンバーのスコアも教えてくれる。

  • アイデア3:ベビーカーに乗って外出している赤ちゃん。おしっこ、ウンチしたときに「おむつを交換してね」のお知らせ。

  • アイデア4:工事現場で働く方の熱中症予防用に、温度・湿度センサーをヘルメットまたは作業着に取り付けて、集中監視。

アイデア1の事前調査

  • アイデア1を実現できるか? 車に持ちこむデバイスはM5stackにする。 ワイバーにネオジウムマグネットをつけて、ガラス越しでも車内にあるM5stack内蔵のHall Sensorが反応するか確認した。

動画はこれ。

よし、反応した。

最終的なイメージは下の図。

20190731_06-57-57.png

M5stackをLINE Thingsのデバイスとして機能させ、enebularを使って、「眠気をさませ」の画像を送る練習。

20190731_04-11-22.png

templateノードのあたりに画像を送るよう指示

{
"replyToken": "{{replyToken}}",
"messages": [
{
"type": "image",
"originalContentUrl": "https://xxxxxxxxxxxxxxx.xxxxx.xx/wakeup.JPG",
"previewImageUrl": "https://xxxxxxxxxxxxxxx.xxxxx.xx/wakeup.JPG"
}
]
}

M5stackのボタンを押したら画像がLINEに送られるようになった。

20190731_07-38-05.png

動画はこれ。

M5Stack内蔵のHall sensorの反応値が高くなったら、LINEに画像を送る仕組みを考える。

Arduinoで以下の通り、LINE Thingsのプログラムと、Hall sensor動作のプログラムを、合体させたが今のところ動かない。
動かしたい。ここが今後の課題です。

setup.ino

#include <M5Stack.h>
#include <BLEServer.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLE2902.h>

// Device Name: Maximum 30 bytes
#define DEVICE_NAME "MyName_M5Stack"

// User service UUID: Change this to your generated service UUID
#define USER_SERVICE_UUID "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
// User service characteristics
#define WRITE_CHARACTERISTIC_UUID "E9062E71-9E62-4BC6-B0D3-35CDCD9B027B"
#define NOTIFY_CHARACTERISTIC_UUID "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

// PSDI Service UUID: Fixed value for Developer Trial
#define PSDI_SERVICE_UUID "E625601E-9E55-4597-A598-76018A0D293D"
#define PSDI_CHARACTERISTIC_UUID "26E2B12B-85F0-4F3F-9FDD-91D114270E6E"

#define TEXT_X (M5.Lcd.width() / 2)
#define TEXT_Y (M5.Lcd.height() / 2 / 2)

BLEServer* thingsServer;
BLESecurity *thingsSecurity;
BLEService* userService;
BLEService* psdiService;
BLECharacteristic* psdiCharacteristic;
BLECharacteristic* writeCharacteristic;
BLECharacteristic* notifyCharacteristic;

bool deviceConnected = false;
bool oldDeviceConnected = false;

class serverCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
   deviceConnected = true;
  };

  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
  }
};

class writeCallback: public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *bleWriteCharacteristic) {
    std::string value = bleWriteCharacteristic->getValue();
    if ((char)value[0] <= 1) {
      if ((char)value[0] == 1) {
        M5.Lcd.fillRect(0, 0, M5.Lcd.width(), M5.Lcd.height() / 2, WHITE);
        M5.Lcd.setTextColor(BLACK);
        M5.Lcd.setTextSize(4);
        M5.Lcd.drawString("LED: ON ", TEXT_X, TEXT_Y);
      }
      else {
        M5.Lcd.fillRect(0, 0, M5.Lcd.width(), M5.Lcd.height() / 2, BLACK);
        M5.Lcd.setTextColor(WHITE);
        M5.Lcd.setTextSize(4);
        M5.Lcd.drawString("LED: OFF", TEXT_X, TEXT_Y);
      }
    }
  }
};

void setup() {
  M5.begin();

  BLEDevice::init("");
  BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT_NO_MITM);

  // Security Settings
  BLESecurity *thingsSecurity = new BLESecurity();
  thingsSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND);
  thingsSecurity->setCapability(ESP_IO_CAP_NONE);
  thingsSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);

  setupServices();
  startAdvertising();

  // M5Stack LCD Setup
  M5.Lcd.setTextDatum(MC_DATUM);
  M5.Lcd.clear(BLACK);
  M5.Lcd.qrcode("https://line.me/R/nv/things/deviceLink", 110, 130, 100, 3);
  M5.Lcd.setTextColor(YELLOW);
  M5.Lcd.setTextSize(2);
  M5.Lcd.drawString("Ready to Connect", TEXT_X, TEXT_Y);
  Serial.println("Ready to Connect");
}

void loop() {
  M5.update();

  if (M5.BtnB.wasPressed()) {
    uint8_t btnValue = 1;
    notifyCharacteristic->setValue(&btnValue, 1);
    notifyCharacteristic->notify();
  } else if (M5.BtnB.wasReleased()) {
    //uint8_t btnValue = 0;
    //notifyCharacteristic->setValue(&btnValue, 1);
    //notifyCharacteristic->notify();
  }

  // Disconnection
  if (!deviceConnected && oldDeviceConnected) {
    delay(500); // Wait for BLE Stack to be ready
    thingsServer->startAdvertising(); // Restart advertising
    oldDeviceConnected = deviceConnected;
    M5.Lcd.fillRect(0, 0, M5.Lcd.width(), M5.Lcd.height() / 2, BLACK);
    M5.Lcd.setTextColor(YELLOW);
    M5.Lcd.setTextSize(2);
    M5.Lcd.drawString("Ready to Connect", TEXT_X, TEXT_Y);
  }
  // Connection
  if (deviceConnected && !oldDeviceConnected) {
    oldDeviceConnected = deviceConnected;
    M5.Lcd.fillRect(0, 0, M5.Lcd.width(), M5.Lcd.height() / 2, BLACK);
    M5.Lcd.setTextColor(GREEN);
    M5.Lcd.setTextSize(2);
    M5.Lcd.drawString("Connected", TEXT_X, TEXT_Y);
  }
}

void setupServices(void) {
  // Create BLE Server
  thingsServer = BLEDevice::createServer();
  thingsServer->setCallbacks(new serverCallbacks());

  // Setup User Service
  userService = thingsServer->createService(USER_SERVICE_UUID);
  // Create Characteristics for User Service
  writeCharacteristic = userService->createCharacteristic(WRITE_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE);
  writeCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
  writeCharacteristic->setCallbacks(new writeCallback());

  notifyCharacteristic = userService->createCharacteristic(NOTIFY_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY);
  notifyCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
  BLE2902* ble9202 = new BLE2902();
  ble9202->setNotifications(true);
  ble9202->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
  notifyCharacteristic->addDescriptor(ble9202);

  // Setup PSDI Service
  psdiService = thingsServer->createService(PSDI_SERVICE_UUID);
  psdiCharacteristic = psdiService->createCharacteristic(PSDI_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ);
  psdiCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);

  // Set PSDI (Product Specific Device ID) value
  uint64_t macAddress = ESP.getEfuseMac();
  psdiCharacteristic->setValue((uint8_t*) &macAddress, sizeof(macAddress));

  // Start BLE Services
  userService->start();
  psdiService->start();
}

void startAdvertising(void) {
  // Start Advertising
  BLEAdvertisementData scanResponseData = BLEAdvertisementData();
  scanResponseData.setFlags(0x06); // GENERAL_DISC_MODE 0x02 | BR_EDR_NOT_SUPPORTED 0x04
  scanResponseData.setName(DEVICE_NAME);

  thingsServer->getAdvertising()->addServiceUUID(userService->getUUID());
  thingsServer->getAdvertising()->setScanResponseData(scanResponseData);
  thingsServer->getAdvertising()->start();
}


/************************************************************************
  M5StackFire internal Hall sensor
************************************************************************/

#define M5STACKFIRE_SPEAKER_PIN 25 // speaker DAC, only 8 Bit
#define HORIZONTAL_RESOLUTION 320
#define VERTICAL_RESOLUTION   240
#define POSITION_OFFSET_Y      20
#define SIGNAL_LENGTH HORIZONTAL_RESOLUTION

uint16_t oldSignal[SIGNAL_LENGTH];
uint16_t adcBuffer[SIGNAL_LENGTH];

float ESP32_hallRead()
{
  float value = 0;
  int count = 400;
  // mean value filter
  for (int n = 0; n < count; n++) value += hallRead();
  return value / count * 10; 
}

float HallOffset = 0;

void setup1()
{
  dacWrite(M5STACKFIRE_SPEAKER_PIN, 0); // make sure that the speaker is quite
  M5.Lcd.begin();
  M5.Lcd.fillScreen( BLACK );
  M5.Lcd.fillRect(10, 1, 150, 160, BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextColor(BLUE, BLACK);
  M5.Lcd.setTextSize(2);

  M5.Lcd.println("ESP32 Hall sensor:");
  HallOffset = ESP32_hallRead(); // callibrate the output value to the magnetic field at start up
  M5.Lcd.setTextSize(2);
}

float LowPassFilteredValue=0;
void showSignal()
{
  int n;
  int oldx;
  int oldy;
  int oldSig;
  int x, y;

  for (n = 0; n < SIGNAL_LENGTH; n++)
  {
    x = n;
    float value = ESP32_hallRead()- HallOffset;
    LowPassFilteredValue+=(value-LowPassFilteredValue)*0.05;
    M5.Lcd.setCursor(220, 1);
    M5.Lcd.print((int)LowPassFilteredValue);M5.Lcd.print("    ");

    y = map(value , -127, 127, VERTICAL_RESOLUTION, POSITION_OFFSET_Y);

    if (n > 0)
    {
      // delete old line element
      M5.Lcd.drawLine(oldx , oldSig, x, oldSignal[n], BLACK );

      // draw new line element
      if (n < SIGNAL_LENGTH - 1) // don't draw last element because it would generate artifacts
      {
        M5.Lcd.drawLine(oldx,    oldy, x,            y, GREEN );
      }
    }
    oldx = x;
    oldy = y;
    oldSig = oldSignal[n];
    oldSignal[n] = y;

//以下に磁石が近づいたらLINE BOTに通知する記述

      if(LowPassFilteredValue>10){
      notifyCharacteristic->notify();
      }

//磁石が近づいたらLINE BOTに通知する記述ここまで

  }
}

//void loop()
//{
//  showSignal();
//}

アイデア1について今後の予定

  • 運転中によそ見をせずに押せるスマートフォンのスイッチ、電気系統を改造することなく反応するスイッチとして、利用用途を考える。眠気防止。神経衰弱ゲーム。移動場所のマーク。docomo 基地局を利用した位置情報のAPIを使ったら、実現できるかも。でもカーナビがあるからいらない。

アイデア2について今後の予定

  • データベースを使って、メンバー4人のスコアを互いにLINE BOTで知らせることができるようにする。腕時計タイプのカッコいい製品が2万円くらいでゴルフショップにすでに売ってる。でも、メンバー4人のスコアを互いに共有できる機能はないので、このアイデアを、動画にして、LINE Things Mini Awardに応募した(2019年9月8日応募)。コードの実装はできていません。アイデアのみで応募。 動画はこちら

アイデア3について今後の予定

  • 漏水センサー、湿り気センサー、匂いセンサーを調査したが、そもそも紙おむつの中にセンサーは入れたら、痛かったり、怪我したりしないか?もっと、いい方法ないか?

アイデア4について今後の予定

  • データベースに値が取り込めるようにする。Firebaseを学ぼう。LINE Things連携はないが、すでに世の中に多くの開発品があり競合多し。
3
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
MikH
まず作って試してみるプロトタイプ派。 ProtoOut Studio 1期生,  Call for Code 2019 Regional Finalist, Call for Code 2020 Regional Finalist, IBM Chamipon 2021 ,  医学博士,   実験室と医療現場をAI・IoT化することミッションに、xMedGear株式会社を設立。
protoout-studio
プロトアウトスタジオは日本初のプロトタイピング専門スクールです。プログラミングだけではなく、企画力と発信力を身に付けて”自分で課題を見つけて実装し、発信し続ける人”を育成しています。 圧倒的なアウトプット力を身に付けましょう。 学生募集中です。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
3
Help us understand the problem. What is going on with this article?