ラベル 07.weblog-tech の投稿を表示しています。 すべての投稿を表示
ラベル 07.weblog-tech の投稿を表示しています。 すべての投稿を表示

2020年8月8日土曜日

mongodb connector for business intelligence

 mongodb connector for business intelligence
って、mongodbをODBCぽいSQL-DBに見せかけるラッパーかな。

https://www.mongodb.com/products/bi-connector

https://docs.mongodb.com/bi-connector/master/


2020年8月7日金曜日

RP3B+のルートパーティションをnfsでマウント

絶不調のでお蔵入りにしていたRaspberry Pi 3B+だが、捨てるには惜しいので、不安定なμSDカードをできるだけ使わない方法で安定するかどうかを検証すべく、以下を行なった。

【USB経由でSDカードを使う】

  •  USB経由でSDカードを使うようにする
    /も/bootもSDカードのまま。ただし、sd→USBアダプタを使って起動させる。

何も設定しなくても、RP3B+は標準でUSBブートするようで、上記はあっさり動いた。

 

上記でも以前より安定して動いたような気がする。

しかし、もう一歩進めて、下記のようにした。

 

【USB経由で/bootさせ、/パーティションはnfsでマウントする】

  • USB経由のSDカードは、/bootだけにする(ほぼread onlyになる)
  • /ファイルシステムは、隣に並んでいるRaspberry Pi 4Bをnfsサーバにして、
    そこからのマウントにする
    (RP4Bのストレージは、USB3経由でマウントしているSSDなので
     SDカードよりは性能も耐久性も良いだろうと)
  •  具体的な方法はNFS Root on Raspberry Pi 4 そのままでいけた。
    (上記ページはraspbianの例もubuntuの例もあり、非常に助かる)

次にやるかもしれないのは、下記。

【PXEブートを使い、tftpで/bootをマウントさせ、/はnfsでマウント】

これができたら、不安定なSDから完全におさらばできる。

それらしい情報は下記にあるので、不安定さが解決しな時には試してみよう。

Raspberry Pi 3 でSDカードなしのネットワークブートをする

Network booting

以上(^^;

 


2020年8月3日月曜日

JSON形式のファイルと名乗るには

{ key: value }
というのが一つのObjectであり
{ key: value }
{ key: value }

というのは、複数のObjectを列記してあるに過ぎず、厳密にはJSONのObjectではない。

よって、上記のような形式のファイルは「JSONのようなもの」であるということになる。

厳密にJSON形式のファイルフォーマットというなら、
[
    { key: value }
    { key: value }
]
という配列(arrey)にする必要がありそうだ。

各種センサーのログを厳密にJSON形式のファイルフォーマットにするのは大変なので
「JSONのようなもの」のファイルにしておこう(^^;

2020年7月30日木曜日

M5Stack COCOA Counter + ENV.2 Sensor + GPS Unit のログファイルをHTTP POSTするスケッチ その1

【主な機能】

【付加機能】
  • ボタンA(左)を押すと、M5Stack-SD-Updaterに遷移する。
  • 読み出すログファイル名、接続するWiFiのSSID/pass、http POSTするURLを
    マイクロSD内の"/GPSlog.conf"という名の初期設定ファイルから読み出すようにした。
    (使用環境に合わせるためのスケッチの修正やリコンパイルを不要にした。)

【かっこ悪いところ】
  • ログファイル内のJSONのフォーマットチェックを一切おこなっていない。
  • http POSTが失敗した時のエラー処理を一切おこなっていない。
  • 何レコードをPOSTしたのかもカウントしていない。

【初期設定ファイル例】
{
    logfile: "/GPSlog.jsn",
    buf: 2048,
    ssid: "secret-SSID-home2.4",
    pass: "secret-password-home",
    url: "http://192.168.0.112:3000/log"
}

【初期設定ファイルの説明】
logfile: ログファイル名
buf: 1レコードのJSON文字列用のバッファ長
ssid: 接続するWiFiのSSID
pass: WiFiのパスワード
url: httpでPOSTするURL   
【スケッチ・ソース】his.GPS.LOG.POST.ino
[code]
// M5Stack ----------------------------------------------------------------
#include <M5Stack.h>
#include "M5StackUpdater.h"
// HTTP -------------------------------------------------------------------
#include <HTTPClient.h>
// JSON -------------------------------------------------------------------
#include <ArduinoJson.h>
// SD ---------------------------------------------------------------------
#include <SPI.h>
#include <SD.h>
// WiFi -------------------------------------------------------------------
#include <WiFi.h>

// CONFIG -----------------------------------------------------------------
struct Config {
  char logfile[12];
  int  buf;
  char ssid[64];
  char pass[64];
  char url[256];
};

Config config;

const char *cnfFileName = "/GPSlog.cnf"; //環境毎に設定

File logFile;

void loadConfiguration(const char *filename, Config &config) {
  File file = SD.open(cnfFileName);
  StaticJsonDocument<512> doc;

  // Deserialize the JSON document
  DeserializationError error = deserializeJson(doc, file);
  if (error)
    Serial.println(F("ERROR while reading config file. using default conf"));

  // Copy values from the JsonDocument to the Config
  strlcpy(config.logfile,
          doc["logfile"] | "/GPSlog.jsn",  //環境毎に設定
          sizeof(config.logfile));
  Serial.println("log file name: " + String(config.logfile));
  config.buf = doc["buf"] | 1024;         //環境毎に設定
  Serial.println("JSON line buffer size: " + String(config.buf));
  strlcpy(config.ssid,
          doc["ssid"] | "SSID-open",  //環境毎に設定
          sizeof(config.ssid));
  Serial.println("SSID: " + String(config.ssid));
  strlcpy(config.pass,
          doc["pass"] | "passowrd",  //環境毎に設定
          sizeof(config.pass));
  Serial.println("pass: " + String(config.pass));
  strlcpy(config.url,
          doc["url"] | "http://example.com:3000/postjson",  //環境毎に設定
          sizeof(config.url));
  Serial.println("http POST url: " + String(config.url));

  // Close the file (Curiously, File's destructor doesn't close the file)
  file.close();
}
// HTTP -------------------------------------------------------------------
bool dohttpPOST(String logstring)
{
  bool b = false;
  HTTPClient http;
  http.begin(config.url);
  http.addHeader("Content-Type", "application/json");
  int status_code = http.POST(logstring);
  Serial.printf("status_code=%d\r\n", status_code);
  if (status_code == 200) {
    String json_response = http.getString();
    Serial.println("respose->"); Serial.println(json_response);
    b = true;
  }
  http.end();
  return b;
}
// WiFi -------------------------------------------------------------------
void connectWiFi() {
  WiFi.mode(WIFI_STA);  //STAモード(子機)として使用
  WiFi.disconnect();    //Wi-Fi切断

  WiFi.begin(config.ssid , config.pass); //環境毎に設定
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("trying WiFi Connection...");
    delay(1000);
  }
  Serial.println("WiFi Connected.");
}

// Inside -----------------------------------------------------------------
void setup() {
  M5.begin();
  M5.Power.begin();
  M5.Lcd.println("Hello!, JSON http.post");

  Serial.begin(115200);
  loadConfiguration(cnfFileName, config);

  //SD -------------------------------------------
  logFile = SD.open(String(config.logfile));
  if (logFile) {
    Serial.println("log file found");
  } else {
    Serial.println("error: opening " + String(config.logfile));
  }

  //WiFI -------------------------------------------
  connectWiFi();

  //HTTP -------------------------------------------
  int pt = 0;
  char readbuf[config.buf] = "";
  while (logFile.available()) {
    readbuf[pt] = logFile.read();
    if (readbuf[pt] == 0x0A) {
      readbuf[pt + 1] = 0;
      String s = readbuf;
      Serial.println("String length=" + String(s.length()));
      Serial.println(s);
      if (dohttpPOST(s)) {
        Serial.println("post OK");
      } else {
        Serial.println("post ERROR");
      }
      pt = 0;
      char readbuf[config.buf] = "";
      delay(50);
    } else {
      pt++;
    }
  }
}

void loop() {
  M5.update();
  M5.Lcd.setTextSize(3);
  M5.Lcd.println();
  M5.Lcd.setTextColor(BLUE, WHITE);
  M5.Lcd.println("log file http.POST done.");
  M5.Lcd.println("A: SDUpdater");
  while (1) {
    if (M5.BtnA.wasReleased()) { //AボタンでSDUpdater
      updateFromFS(SD);
      ESP.restart();
    }
    delay(100);
    M5.update(); // update button state
  }
}
// Arranged and written by 柴田(ひ)
[/code]


M5Stack COCOA Counter + ENV.2 Sensor + GPS Unit その4


【変更内容】
  • 出力ファイル名の変更
    →マイクロSDカードに"GPSlog.jsn"というファイル名で
     JSONフォーマットのログを出力する。


【既知のバグ】
  • GPSからの取得データ値がおかしなことがある。
    →あれこれ調べたけど、断念(^^;

【今後の予定】
  • JSON形式のログをhttp POSTで
    node.js+express+mongoDBで構築している
    ログ収集サーバにuploadするスケッチを作成する。
    →一応できたので、別に書いときます。

  • コテコテコーディングからArduino_JSONを利用するように書き直し。
    →変更してない。
     http POSTするスケッチの中でちょっとだけ使用。


  • ログ収集サーバ側では、JSON→GPX変換して、
    googleMap等に表示できるようにする。
    →まだ未着手。

  • 同じくサーバサイドで、グラフ表示などの機能を作る。
    生成したグラフは、Blogger上のこのブログに自動投稿させる。
    →同じく未着手。

【出力ファイル内の例】
{ "class": "TPV" ,"mode": 3 ,"time": "2020-07-30T06:41:13Z" ,"lat": 35.123456 ,"lon": 139.123456 ,"alt": 26.5 ,"track": 185.950000 ,"speed": 0.0 ,"ble": 15 ,"cocoa": 4 ,"temp": 27.4 ,"humidity": 70.0 ,"pressure": 1015.5 }
{ "class": "TPV" ,"mode": 3 ,"time": "2020-07-30T06:41:24Z" ,"lat": 35.123456 ,"lon": 139.123456 ,"alt": 25.2 ,"track": 185.950000 ,"speed": 0.0 ,"ble": 16 ,"cocoa": 5 ,"temp": 27.4 ,"humidity": 70.0 ,"pressure": 1015.5 }
{ "class": "TPV" ,"mode": 3 ,"time": "2020-07-30T06:41:34Z" ,"lat": 35.123456 ,"lon": 139.123456 ,"alt": 25.3 ,"track": 185.950000 ,"speed": 0.0 ,"ble": 15 ,"cocoa": 6 ,"temp": 27.4 ,"humidity": 70.0 ,"pressure": 1015.5 }


【スケッチ・ソース】his.GPS.LOG.SAVE.ino
[code]
// M5Stack ----------------------------------------------------------------
#include <M5Stack.h>
#include "M5StackUpdater.h"
// BLE & Cocoa ------------------------------------------------------------
#include <BLEDevice.h>
// ENV2 -------------------------------------------------------------------
/* add library Adafruit_BMP280 & Adafruit_SHT31 from library manage */
#include <Adafruit_Sensor.h>
#include <Adafruit_SHT31.h>
#include <Wire.h> //The SHT31 uses I2C comunication.
#include <Adafruit_BMP280.h>
// GPS --------------------------------------------------------------------
#include <TinyGPS++.h>
// SD ---------------------------------------------------------------------
#include <SPI.h>
#include <SD.h>
// BLE & Cocoa ------------------------------------------------------------
int scanTime = 5;
BLEScan* pBLEScan;
const int chipSelect = 4;
bool onBeep = true;

//接触確認アプリのUUID
const char* cocoaUUID = "0000fd6f-0000-1000-8000-00805f9b34fb";
int cocoaCnt = 0; //time out in seconds

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      if (advertisedDevice.haveServiceUUID()) {
        if (strncmp(advertisedDevice.getServiceUUID().toString().c_str(), cocoaUUID, 36) == 0) {
          cocoaCnt++;
          if (onBeep) {
            M5.Speaker.beep();
            delay(10);
            M5.Speaker.mute();
          }
          M5.Lcd.setCursor(0, 110);
          M5.Lcd.setTextSize(2);
          M5.Lcd.setTextColor(GREEN, BLACK);
          M5.Lcd.printf("%d ", cocoaCnt);
          M5.Lcd.setTextSize(1);
        }
      }
      M5.Lcd.println(advertisedDevice.toString().c_str());
      M5.Lcd.setTextSize(1);
      M5.Lcd.setTextColor(WHITE, BLACK);
    }
};

void setupBLE() {
  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);  // less or equal setInterval value
}
// ENV2 -------------------------------------------------------------------
Adafruit_SHT31 sht31 = Adafruit_SHT31();
Adafruit_BMP280 bme;

bool hasSHT31 = false;
bool hasBMP280 = false;
float tmp = 100;
float hum = 0;
float pressure = 0;

void setupENV2() {
  //ENV2 sensor on I2C setup
  Wire.begin();
  Serial.println(F("ENV.2 Chk"));

  if (sht31.begin(0x44)) {   // Set to 0x45 for alternate i2c addr
    hasSHT31 = true;
    Serial.println("SHT31 Ok");

    Serial.print("Heater: ");
    if (sht31.isHeaterEnabled())
      Serial.println("Ena");
    else
      Serial.println("Dis");
  }

  if (bme.begin(0x76)) {
    hasBMP280 = true;
    Serial.println("BMP280 Ok");
  }
}
// GPS --------------------------------------------------------------------
//bool hasRTC = false;
bool hasGPS = false;
TinyGPSPlus gps; // The TinyGPS++ object
HardwareSerial hsGps(2);// The serial connection to the GPS device
static const uint32_t GPSBaud = 9600;

void setupGPS() {
  hsGps.begin(GPSBaud);
  delay(500);

  if (hsGps.available() > 0) {
    hasGPS = true;
    Serial.println("GPS Ok");
  }
}
// SD ---------------------------------------------------------------------
// log file name
const char* logfile = "/GPSlog.jsn";
// Inside -----------------------------------------------------------------
unsigned char bright = 0x03;
unsigned char brightPitch = 0x10;
//文字列
const char* logJSON = "{ \"class\": \"TPV\" ,\
\"mode\": 3 ,\
\"time\": \"%d-%02d-%02dT%02d:%02d:%02dZ\" ,\
\"lat\": %lf ,\
\"lon\": %lf ,\
\"alt\": %.1f ,\
\"track\": %lf ,\
\"speed\": %.1f ,\
\"ble\": %d ,\
\"cocoa\": %d ,\
\"temp\": %.1f ,\
\"humidity\": %.1f ,\
\"pressure\": %.1f }
";

// ------------------------------------------------------------------------
void setup() {

  // Initialize the M5Stack
  M5.begin();
  M5.Power.begin();
  M5.Lcd.setBrightness(bright);
  M5.Lcd.setTextSize(1);
  M5.Lcd.println("Hello!, COCOA Scan");

  Serial.begin(115200);

  setupBLE();
  setupENV2();
  setupGPS();

  if (digitalRead(BUTTON_A_PIN) == 0) {
    Serial.println("Will Load menu binary");
    updateFromFS(SD);
    ESP.restart();
  }

}

void loop() {
  // print all found BLE devices
  M5.Lcd.setTextSize(1);

  BLEScanResults foundDevices = pBLEScan->start(scanTime, false);

  // print counts of BLE devices
  int sumdev = foundDevices.getCount();

  // print env2 data
  if (hasSHT31) {
    tmp = sht31.readTemperature();
    hum = sht31.readHumidity();
  }
  if (hasBMP280) {
    pressure = bme.readPressure() / 100;
    // hPa = Pa / 100;
  }

  while (hsGps.available() > 0) {
    gps.encode(hsGps.read());
  }

  Serial.printf(logJSON, gps.date.year(), gps.date.month(), gps.date.day(),
                gps.time.hour(), gps.time.minute(), gps.time.second(),
                gps.location.lat(), gps.location.lng(), gps.altitude.meters(), gps.course.deg(),
                gps.speed.mps(), sumdev, cocoaCnt, tmp, hum, pressure);
  Serial.println();

  // SDカードへの書き込み処理(ファイル追加モード)
  // SD.beginはM5.begin内で処理されているので不要
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dfile = SD.open(logfile, FILE_APPEND);

  // if the file is available, write to it:
  if (dfile) {
    dfile.printf(logJSON, gps.date.year(), gps.date.month(), gps.date.day(),
                 gps.time.hour(), gps.time.minute(), gps.time.second(),
                 gps.location.lat(), gps.location.lng(), gps.altitude.meters(), gps.course.deg(),
                 gps.speed.mps(), sumdev, cocoaCnt, tmp, hum, pressure);
    dfile.println();
  }

  // clear screen and set cursor to the top
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.printf(logJSON, gps.date.year(), gps.date.month(), gps.date.day(),
                gps.time.hour(), gps.time.minute(), gps.time.second(),
                gps.location.lat(), gps.location.lng(), gps.altitude.meters(), gps.course.deg(),
                gps.speed.mps(), sumdev, cocoaCnt, tmp, hum, pressure);
  M5.Lcd.println();

  //Button controll
  M5.Lcd.setTextSize(3);
  M5.Lcd.println();
  M5.Lcd.setTextColor(BLUE, WHITE);
  M5.Lcd.println("A: SDUpdater");
  M5.Lcd.println("B: Beep on/off");
  M5.Lcd.println("C: Brightness");

  int timer = 100;
  while (timer--) {
    if (M5.BtnA.wasReleased()) { //AボタンでSDUpdater
      updateFromFS(SD);
      ESP.restart();
    } else if (M5.BtnB.wasReleased()) { //Bボタンでbeepをon/off切り替える
      onBeep = !onBeep;
    } else if (M5.BtnC.wasReleased()) { //Cボタンで輝度を変更
      bright += brightPitch;
      M5.Lcd.setBrightness(bright);
    }
    delay(50);
    M5.update(); // update button state
  }

  //init for next loop
  dfile.close();
  pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory
  cocoaCnt = 0;

  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.setCursor(0, 110);
  M5.Lcd.setTextSize(1);
}

// Arranged and written by 柴田(ひ)
/* BLE
   Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
   Ported to Arduino ESP32 by Evandro Copercini
*/
/* Cocoa
   Thanks to https://gist.github.com/ksasao/0da6437d3eac9b2dbd675b6fee5d1117
   by https://gist.github.com/ksasao
*/
/* GPS
   This sample sketch demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.
   by Mikal Hart
*/
/* SD
   SD card wrie routine
   https://raspberrypi.mongonta.com/howto-write-csv-to-sdcard-on-m5stack/
*/
[/code]

2020年7月25日土曜日

node.jp + express + mongoDB関連のインストール

node.jp と express のインストール

下記ページがかなり参考になったけど、肝心の「最終結果のjsソース」が書かれてないので、やっぱりハマった。


mongoDBをubuntuにインストール

ここが本家なのか?ということも知らないが(^^;

n コマンドの出力結果
  ο node/12.18.3

Use up/down arrow keys to select a version, return key to install, d to delete, q to quit

npm list -g コマンドの出力結果
ちょっと多すぎるので省略
とりあえず、expressを入れとけば、body-parserは入れなくて良いようだ。


node.jp + express + mongoDB 作業メモ

  1. インストールしたPATH
    /var/www/node/express_mongodb

  2. 起動コマンド
    npx nodemon app.js

  3. app.js
const express = require('express');
const app = express();
const mongoose = require('mongoose');
const userRouter = require('./routes/user');

app.use('/user', userRouter);
//app.use(express.json());

const port = 3000;

const options = {
    useUnifiedTopology : true,
    useNewUrlParser : true
}

mongoose.connect('mongodb://127.0.0.1/test_db',options);

const db = mongoose.connection;

db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => console.log('Database connection successful'));
app.get('/', (req, res) =>
    res.sendFile('/var/www/node/express_mongodb/test.html'))

app.listen(port,
    () => console.log(`Example app listening on port ${port}!`));
 
  1. models/User.js
    const mongoose = require('mongoose');

    const UserSchema = mongoose.Schema({
      name: String,
      age: Number
    });

    module.exports = mongoose.model('User',UserSchema);
     
  2. routes/user.js
    const express = require('express');

    const router = express.Router();
    const User = require('../models/User');

    router.use(express.json());
    router.use(express.urlencoded({ extended: false }));

    router.get('/', async (req, res) => {
        const users = await User.find({});
        res.json(users);
    });

    router.get('/:userID',(req, res)=>{
        User.findById(req.params.userID,(err,user)=>{
            if (err) console.log('error');
            res.send(user);
        });
    });

    router.post('/', async (req,res)=>{
        console.log(req.body);

        const user = new User({
            name: req.body.name,
            age: req.body.age
        });

        const savedUser = await user.save();
        res.json(savedUser);

    });

    router.delete('/:userID',async (req,res)=>{
        const user = await User.remove({_id: req.params.userID});
        res.send(user);
    });

    router.patch('/:userID',async (req,res)=>{
        console.log(req.body.age);
        const user = await User.updateOne({_id: req.params.userID},{$set:{age:re
    q.body.age}});
        res.send(user);
    });

    module.exports = router;

  3. test.html
    <!DOCTYPE html>
    <html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>入力フォーム</title>
    </head>
    <body>
    <h1>入力フォーム</h1>
    <form action="/user" method="POST">
        name <input type="text" name="name"><br>
        age <input type="text" name="age"><br>
        <button type="submit">送信</button>
    </form>
    </body>
    </html>

  4. 確認方法
  • http://server:3000/
    POSTする入力フォームが表示される
  • http://server:3000/user
    GETで登録一覧がJSON形式で出力される
以上、作業途中メモ。

2020年7月16日木曜日

M5Stack COCOA Counter & ENV.2 Sensor




[code]
/*
   Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
   Ported to Arduino ESP32 by Evandro Copercini
*/
/*
   Thanks to https://gist.github.com/ksasao/0da6437d3eac9b2dbd675b6fee5d1117
   by https://gist.github.com/ksasao
*/
/*
   SD card wrie routine
   https://raspberrypi.mongonta.com/howto-write-csv-to-sdcard-on-m5stack/
*/

//////////////////////////////////////////////////////////////////////////////////
#include <M5Stack.h>

#include <BLEDevice.h>
//#include <BLEUtils.h>
//#include <BLEScan.h>
//#include <BLEAdvertisedDevice.h>

//////////////////////////////////////////////////////////////////////////////////
/*
   note: need add library Adafruit_BMP280 & Adafruit_SHT31 from library manage
*/
#include <Adafruit_SHT31.h>
#include <Wire.h> //The SHT31 uses I2C comunication.
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>

//////////////////////////////////////////////////////////////////////////////////
#include <SPI.h>
#include <SD.h>

//////////////////////////////////////////////////////////////////////////////////
Adafruit_SHT31 sht31 = Adafruit_SHT31();
Adafruit_BMP280 bme;

//time out in seconds
int scanTime = 5;
BLEScan* pBLEScan;

const int chipSelect = 4;

//接触確認アプリのUUID
const char* uuid = "0000fd6f-0000-1000-8000-00805f9b34fb";
int cocoaCnt = 0;

//log file name
const char* logfile = "/datalog.txt";

//文字列
const char* sumdevStr = "Sum";
const char* cocoaStr = " Cocoa";
const char* envStr = "Temp:  %3.1fC\r\nHumid: %3.1f%%\r\nPress: %3.0fhPa\r\n";
//RTC買うまで固定
const char* dateStr = "2020.07.15 10:10:00 ";

//Sensor flag
bool hasSHT31 = false;
bool hasBMP280 = false;
float tmp = 100;
float hum = 0;
float pressure = 0;

//Other flags,Params
bool onBeep = true;
int bright = 20;
int brightPitch = 10;
//////////////////////////////////////////////////////////////////////////////////
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      if (advertisedDevice.haveServiceUUID()) {
        if (strncmp(advertisedDevice.getServiceUUID().toString().c_str(), uuid, 36) == 0) {
          cocoaCnt++;
          if (onBeep) {
            M5.Speaker.beep();
            delay(10);
            M5.Speaker.mute();
          }
          M5.Lcd.setCursor(0, 110);
          M5.Lcd.setTextSize(2);
          M5.Lcd.setTextColor(GREEN, BLACK);
          M5.Lcd.printf("%d ", cocoaCnt);
          M5.Lcd.setTextSize(1);
        }
      }
      M5.Lcd.println(advertisedDevice.toString().c_str());
      M5.Lcd.setTextSize(1);
      M5.Lcd.setTextColor(WHITE, BLACK);
    }
};

//////////////////////////////////////////////////////////////////////////////////

void setup() {

  // Initialize the M5Stack
  M5.begin();
  M5.Power.begin();
  M5.Lcd.setBrightness(bright);
  M5.Lcd.setTextSize(1);
  M5.Lcd.println("Hello!, cacoa BLE Scan");

  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);  // less or equal setInterval value

  Wire.begin();
  Serial.println(F("ENV2 Unit(SHT31 and BMP280) test..."));

  if (sht31.begin(0x44)) {   // Set to 0x45 for alternate i2c addr
    hasSHT31 = true;
    Serial.println("Found SHT31");

    Serial.print("Heater Enabled State: ");
    if (sht31.isHeaterEnabled())
      Serial.println("ENABLED");
    else
      Serial.println("DISABLED");
  }

  if (bme.begin(0x76)) {
    hasBMP280 = true;
    Serial.println("Found a valid BMP280 sensor");
  }

}

void loop() {
  // print all found BLE devices
  M5.Lcd.setTextSize(1);
  BLEScanResults foundDevices = pBLEScan->start(scanTime, false);

  // clear screen and set cursor to the top
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.println(dateStr);

  // print counts of BLE devices
  int sumdev = foundDevices.getCount();

  M5.Lcd.setTextSize(3);
  M5.Lcd.print(sumdevStr);
  M5.Lcd.setTextColor(RED, BLACK);
  M5.Lcd.print(sumdev);

  // print count of cocoa APPs
  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.print(cocoaStr);
  M5.Lcd.setTextColor(GREEN, BLACK);
  M5.Lcd.println(cocoaCnt);

  // print env2 data
  if (hasSHT31) {
    tmp = sht31.readTemperature();
    hum = sht31.readHumidity();
  }
  if (hasBMP280) {
    pressure = bme.readPressure() / 100;
    // hPa = Pa / 100;
  }

  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.printf(envStr, tmp, hum, pressure);

  // print to the serial port too
  Serial.println(dateStr);
  Serial.print(sumdevStr);
  Serial.println(sumdev);
  Serial.print(cocoaStr);
  Serial.println(cocoaCnt);
  Serial.printf(envStr, tmp, hum, pressure);

  // SDカードへの書き込み処理(ファイル追加モード)
  // SD.beginはM5.begin内で処理されているので不要
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dfile = SD.open(logfile, FILE_APPEND);

  // if the file is available, write to it:
  if (dfile) {
    dfile.println(dateStr);
    dfile.print(sumdevStr);
    dfile.print(sumdev);
    dfile.print(cocoaStr);
    dfile.println(cocoaCnt);
    dfile.printf(envStr, tmp, hum, pressure);

    dfile.close();
  }

  //Button controll
  M5.Lcd.setTextSize(3);
  M5.Lcd.println("");
  M5.Lcd.setTextColor(BLUE, WHITE);
  M5.Lcd.println("A: Beep on/off");
  M5.Lcd.println("B: DOWN bright");
  M5.Lcd.println("C: UP   bright");

  int timer = 100;
  while (timer--) {
    if (M5.BtnA.wasReleased()) { //Aボタンでbeepをon/off切り替える
      onBeep = !onBeep;
    } else if (M5.BtnB.wasReleased()) { //Bボタンで輝度を下げる
      bright -= brightPitch;
    } else if (M5.BtnC.wasReleased()) { //Cボタンで輝度を上げる
      bright += brightPitch;
    }
    M5.Lcd.setBrightness(bright);
    delay(70);
    M5.update(); // update button state
  }

  //init for next loop
  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.setCursor(0, 110);
  M5.Lcd.setTextSize(1);


  pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory
  cocoaCnt = 0;

}
// Arranged and written by 柴田(ひ)
[/code]

2020年7月14日火曜日

M5Stack用環境センサユニット ver.2(ENV II)の動作テスト

とりあえず、動いた。



M5StackのサンプルコードがENV. IIではなく、旧版のENVのものしかなく、
センサーの種類が違ったので、ちょいと手間取った。


/*
   note: need add library Adafruit_BMP280 & Adafruit_SHT31 from library manage */ #include <M5Stack.h> #include <Adafruit_SHT31.h> #include <Wire.h> //The SHT31 uses I2C comunication. #include <Adafruit_Sensor.h> #include <Adafruit_BMP280.h> Adafruit_SHT31 sht31 = Adafruit_SHT31(); //DHT12 dht12; //Preset scale CELSIUS and ID 0x5c. Adafruit_BMP280 bme; void setup() {  M5.begin();  M5.Power.begin();  Wire.begin();  M5.Lcd.setBrightness(10);  Serial.println(F("ENV2 Unit(SHT12 and BMP280) test..."));  if (! sht31.begin(0x44)) {   // Set to 0x45 for alternate i2c addr    Serial.println("Couldn't find SHT31");    while (1) delay(1);  }  Serial.print("Heater Enabled State: ");  if (sht31.isHeaterEnabled())    Serial.println("ENABLED");  else    Serial.println("DISABLED");  if (! bme.begin(0x76)) {    Serial.println("Could not find a valid BMP280 sensor, check wiring!");    M5.Lcd.println("Could not find a valid BMP280 sensor, check wiring!");    while (1) delay(1);  }  M5.Lcd.clear(BLACK);  M5.Lcd.println("ENV Unit test..."); } void loop() {  float tmp = sht31.readTemperature();  float hum = sht31.readHumidity();  float pressure = bme.readPressure() /100 ;  Serial.printf("Temperatura: %2.2f*C  Humedad: %0.2f%%  Pressure: %0.2fhPa\r\n", tmp, hum, pressure);  M5.Lcd.setCursor(0, 0);  M5.Lcd.setTextColor(WHITE, BLACK);  M5.Lcd.setTextSize(3);  M5.Lcd.printf("Temp: %2.1fC  \r\nHumi: %2.0f%%  \r\nPressure:%2.0fhPa\r\n", tmp, hum, pressure);  delay(1000); }

2015年11月2日月曜日

El CapitanでRadioShark2が動かない(対策その2)

しかし、Audacityでは指定日時の1回分の予約は出来るものの、
RadioShark2付属ソフトのような
「毎週日曜日の14時から55分間、山下達郎のSunday Song Bookを録音」
というような設定はできないようだった。

また、Audacityは機能がいっぱいありすぎて、
「バッチファイル的に、一定時間録音して、音声ファイルを出力しておしまい」
というシンプルな用途には向いていない感じだった。

「うーん、Mac OS Xでcrontabって使えるのか?」とか、
「Audacityをコマンドラインで起動して、予約録音のパラメータを引数にできるのか?」、
「いやいや録音だけなのだから、もっとシンプルなソフトはないのか?」など
あれこれ調べていると、用途にドンピシャなナイスな(^^;ソフトを発見した。

MacFeeling Software
マックな感じのソフト達

QTAir(キューティーエアー)
というもの。

録音設定で音源も設定できるので、RadioShark2を入力源にすると、それだけで外部に音声が流れてきた。
 #「プレビュー音を出さない」をチェックすると、聞こえなくも出来る。
 #ちなみに、QTAirインストール直後の初期設定では「プレビュー音」がありだったので、
 #すでに登録していたSondFlower+LadioCastの音声出力とmixされて、しかも微妙に時間にディレイがあり
 #エコーがかかったような音声で聞こえた(^^;
さらに、出力ファイル形式の指定もできて、至れり尽くせり。

試しにリアルタイムで録音してみたけど、タイムスタンプ付きのファイル名が出力され
いい感じです。

予約設定は「繰り返し」に曜日指定が出来るので、まさにドンピシャ!です。
テストで5分ほど予約録音してみましたが、裏でiTunesで音楽を聴きながらでも
全く問題なく録音できていました。

せっかくFMアンテナを立てたので、RadioShark2も、もう少し使っていけそうだ。

El CapitanでRadioShark2が動かない(対策その1)

Radio Shark2を接続してFM福岡録音専用機(ちょっと嘘)としているMac Miniを
よせばいいのに下調べもせずにEl Capitanにupgradeしました。

 #これがまた、普段と同じくディスプレイを接続しないまま
 #VNC経由でupgradeして、
 #途中でどうにもならんかったりした(^^;のですが、
 #upgradeそのものは無事完了

動作確認したところ、Radio Shark2のアプリそのものは動いていて、
選局などは動くのですが、どうにも音が出ません。

 #「システム環境設定」でも「Radio Shark2」は見えていて、
 #しかもレベルメータが動いているので、音声が出ていることまで
 #Mac OS Xからも認識している感じなのですが...。

あれこれ調べると、
OS X El Capitan: Working & Not Working Apps
の"Not Working"の欄にRadio Sharkの名前が...。
しかし
RadioSHARK (app works but gets no sound from device).
Workaround: Use Audio Hijack 3.1.1 to round sound from RadioSHARK input to Line Out

という、気になる記述があった。
なんとかなるのか!?...と思いAudio Hijackというものをダウンロードして
あれこれ操作すると確かに音声が流れてきた(^^)。

しかし、Audio Hijackは有償ソフトであり、フリーのまま使うと
10分ほどでホワイトノイズがミックスされた音声出力となった。

「現在の音声が聞こえないのはEl Capitanのバグであり、そのうち直る(^^;」と考え、
購入せず(^^;にできる方法はないかとあれこれ調べてみた。

Audio Hijackと同じように、AudioFlowerというものがMac OS X上の仮想オーディオデバイスとなり、
同じようなことができそうな気配であった。

これまたAudioFlowerもEl Capitanではすんなり動かないことがNet上で報告されていたが、
SoundFlower-2.0b2.dmgというものを探し出し、Audacityでのタイマー録音も出来たし、
LadioCastというmixerソフトをつかって、ライブでのラジオ聴取も出来るようになりました\(^^)/。
 #Net上にAudioFlower Audacityで検索すると、いっぱい出てきます。

その2に続く

2011年3月27日日曜日

Firefox 4.0

Firefox 4.0にアップデートしてみたのは良いんだけど、まだボタン配置などに慣れないなぁ。
Firefox4.0.png
プラグインの対応も追いついていないので、ちょっとだけ困っていますが、
動きは確かに軽快になった気がする。

2011年1月11日火曜日

I18N Helper Plugin

PostTweetプラグイン v1.0.3でのTweetが上手く行かなかったので、ログを見たところ、
PostTweet: Twitterへの投稿に失敗しました。(twitterから応答を得られません。(utf8 "\xA5" does not map to Unicode at /usr/lib/perl/5.10/Encode.pm line 162. ) )

てな有様。
うーむ、世の中unicodeなのかぁ。

ちょいと調べたところ、mattsun.jp_blog: ●MT→Twitterへの自動投稿にて、同じ現象を発見した。
解決策も示されており、I18N Helper Pluginを使えば良いとのこと。ありがたい。
早速、本pluginを頂き、/plugins/PostTweet/tmpl/message_format.tmplを下記のように変更。
<mt:setvar name="title_len" value="140" />
<mt:setvarblock name="title"><mtencodetext to="utf8"><mt:entrytitle remove_html="1" /></mtencodetext></mt:setvarblock>
<mt:setvarblock name="link"> - <mt:entryshortenedpermalink /></mt:setvarblock>
<mt:setvarblock name="link_len"><mt:var name="link" count_characters="1" /></mt:setvarblock>
<mt:setvar name="title_len" op="-" value="$link_len" />
<mt:var name="title" trim_to="$title_len" /><mt:var name="link" />

これで良さげな感じ。

PostTweetプラグイン v1.0.3

エムロジック放課後プロジェクトから、
PostTweetプラグイン v1.0.3を頂いて、設定してみた。


前作のPostToTwitterを使っていたのだが、いつの間にか動いていなかったことに、本日のセミナー後に気がついた(^^;

常日頃、つぶやけるインフラが私自身にないのが辛い。

2010年8月7日土曜日

AWS Webサイト日本語化

日本語化したという案内メールが届いた。
��今まで、日本語じゃなかったっけな?(^^;

http://aws.amazon.com/jp/


2010年6月22日火曜日

tejimaya.com

OpenPNE開発元の手嶋屋さんのプレゼンを聞くことが出来た。
色々感銘を受けたのだが、最も感じ入ったのは下記のページ。

tejimaya.com-20100617.png

ビジネス面から見たオープンソース開発の良いところを凝縮して示している。
すばらしい。

プレゼン全文は手島屋 社長BLOG
20100617 リナックスファウンデーション講演資料
にて公開されている。

2009年11月23日月曜日

Google Chrome OS

Google Chrome OS 開発版 ダウンロード提供開始とのことで、試してみた。
とりあえず、VMWare上で起動。
GoogleChromeOS-boot-2009-11-22.png


起動後は、ブラウザ画面だけしか見えない感じ。
GoogleChromeOS-Screen-2009-11-22.png
本当に、こっち側はブラウザブートローダだけになっちゃったなぁ。
consoleがないと、何となく不安(^^;