編集履歴一覧に戻る
Gooseのアイコン画像

Goose が 2021年05月08日16時16分59秒 に編集

初版

タイトルの変更

+

obniz Board 1Y で Numbers 定期購入チケットの当選確認

タグの変更

+

obniz

+

obnizIoTコンテスト

+

Nodejs

+

MAX7219

+

obnizBoard1Y

メイン画像の変更

メイン画像が設定されました

本文の変更

+

# 作品概要 ![](https://camo.elchika.com/2562f074aec66c80148df887251a2dad1a69673b/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f31353061386436332d313534352d346662652d393230342d3266396336646465656163332f39653836663335622d626533352d343137332d383033652d306334383361313439636561/) - 毎日定刻にみずほ銀行の当選番号案内サイトから Numbers の当選番号を取得して7Seg に表示します。(左側:Numbers4、右側:Numbers3) - 予め定義しておいた定期購入チケットと比較して当選判定(ストレート/ボックス/セット/ミニ)を行います。 - 「あたり」の場合、LEDをグラデーション点灯させます。「はずれ」の場合、LEDを青色に点灯させます。 - 約1時間、表示/点灯した後、翌日までスリープします。 # 使い方 ### デモ動画 @[youtube](https://youtu.be/KVs79G-9WaY) ### 定期購入チケット(Numbers4)の設定方法 app.js の先頭に定義している定数「const tickets4」の内容を書き換えます。 ```javascript:Numbers4定期購入チケット定義 // **************************************************************** // * Numbers4 定期購入チケット定義 // **************************************************************** // 購入番号と購入タイプを定義します。入力チェックはしていないので下記例を参考に正しく入力してください。 // const tickets4 = [['購入番号(9999)','購入タイプ(straight/box/set)'],['9999','xxxx'],・・・]; // 定義方法 // const tickets4 = [['1234', 'straight'], ['5678', 'box'], ['9012', 'set']]; // 定義例 // const tickets4 = []; // 未購入の場合の定義例 const tickets4 = [['1234', 'straight'], ['5678', 'box'], ['9012', 'set']]; ``` ### 定期購入チケット(Numbers3)の設定方法 app.js の先頭に定義している定数「const tickets3」の内容を書き換えます。 ```javascript:Numbers3定期購入チケット定義 // **************************************************************** // * Numbers3 定期購入チケット定義 // **************************************************************** // 購入番号と購入タイプを定義します。入力チェックはしていないので下記例を参考に正しく入力してください。 // const tickets4 = [['購入番号(999)','購入タイプ(straight/box/set/mini)'],['999','xxxx'],・・・]; // 定義方法 // const tickets3 = [['123', 'straight'], ['456', 'box'], ['789', 'set'], ['01', 'mini']]; // 定義例 // const tickets3 = []; // 未購入の場合の定義例 const tickets3 = [['123', 'straight'], ['456', 'box'], ['789', 'set'], ['01', 'mini']]; ``` ### スリープ解除時刻の設定方法 app.js の先頭に定義している定数「const sleepReleaseDatetime 」の内容を書き換えます。 ```javascript:スリープ解除日時の定義 // スリープ解除日時(翌日の20時の例) const sleepReleaseDatetime = new Date( currentDatetime.getFullYear(), // 年(yyyy) currentDatetime.getMonth(), // 月(mm) currentDatetime.getDate() + 1, // 日(dd) 20, // 時(hh) 0, // 分(mm) 0 // 秒(ss) ); ``` ### 起動方法 ``` node app.js ``` # ハードウェア製作 ### 部品 | 部品 | 説明 | 参考URL | |:---|:---|:---| | obniz Board 1Y | obniz IoT コンテスト提供品 [OS Ver 3.4.5] | https://obniz.com/ja/products/obnizboard#areapdctSpec | | 7セグメントLED | 7SegmentLED_MAX7219 | https://www.amazon.co.jp/gp/product/B01D0WSCJA | | フルカラーLED | LA058GBRC-A | https://www.marutsu.co.jp/pc/i/838245/ | | カーボン抵抗 | 100Ω × 3本 | | | 電線 | | | | ピンヘッダソケット | 短く切断加工 | https://akizukidenshi.com/catalog/g/gC-03077/ | | 両端ロングピンヘッダ | 短く切断&片側を手曲げ加工 | https://akizukidenshi.com/catalog/g/gC-09056/ | | ユニバーサル基盤 | 7.2cm(縦)× 4.7cm(横) | https://www.sunhayato.co.jp/material2/ucb01/item_735 | | スペーサー | | | | USB-C ケーブル | ケーブル長 約15cm | | | モバイルバッテリー | cheero Slim 5000mAh IoT機器対応 CHE-104-SI-IOT |https://www.amazon.co.jp/gp/product/B07W3Q8K6Z | | 木製ケース | 13cm(縦)× 17cm(横)× 5cm(高さ)[100円Shop] | | | アクセサリー | 招き猫[100円Shop] | | ### 道具 | 道具 | 説明 | 参考URL | |:---|:---|:---| | はんだごて | HAKKO PRESTO 984-01 | https://www.hakko.com/japan/products/hakko_presto.html | | はんだ | goot SD-60 | https://www.goot.jp/products/detail/sd_60 | | はんだ吸取線 | CP-3015 | https://www.goot.jp/products/detail/cp_3015 | | ニッパー | | | | ワイヤーストリッパー | VESSEL 3500E-2 | https://www.vessel.co.jp/product/stripper/detail/141012 | | マスキングテープ | | | ### 設計図 ![](https://camo.elchika.com/b631cf5b5f976e8962078dbdb440531f25b5e72c/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f31353061386436332d313534352d346662652d393230342d3266396336646465656163332f32663864633434332d306430622d343830332d613564342d333164633861393438363963/) ### 組み立て ![全体像](https://camo.elchika.com/401c052ba1a4746af4ff90bcda7bd272335c9e6c/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f31353061386436332d313534352d346662652d393230342d3266396336646465656163332f34666466643235332d323661392d346266392d613035332d656662616430326636346131/) ![裏配線](https://camo.elchika.com/95ac5fb208f6f14fc12d123d1d0255e47b7310b8/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f31353061386436332d313534352d346662652d393230342d3266396336646465656163332f63323531633930372d653039352d346632612d393334312d326338646236303861383764/) ![箱の中](https://camo.elchika.com/1a7f1e320de2666564912568abac5a376df33532/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f31353061386436332d313534352d346662652d393230342d3266396336646465656163332f64383961623066392d653666322d346163392d616631642d663939356139393962643464/) # ソフトウェア製作 ### 開発環境 | 環境 | 参考 | |:---:|:---| | OS | Windows 10 Home | | Node.js | LTS 14.15.4 https://nodejs.org/ja/download/ | | npm | 6.14.11 | | obniz ライブラリ | https://github.com/obniz/obniz | | puppeteer ライブラリ | https://github.com/puppeteer/puppeteer | | エディタ | Microsoft Visual Studio Code https://code.visualstudio.com/download| ### Nodejsプロジェクトの作成とパッケージのインストール ``` npm init npm install obniz npm install puppeteer ``` ### ソースコード ```javascript:app.js // **************************************************************** // * Numbers4 定期購入チケット定義 // **************************************************************** // 購入番号と購入タイプを定義します。入力チェックはしていないので下記例を参考に正しく入力してください。 // const tickets4 = [['購入番号(9999)','購入タイプ(straight/box/set)'],['9999','xxxx'],・・・]; // 定義方法 // const tickets4 = [['1234', 'straight'], ['5678', 'box'], ['9012', 'set']]; // 定義例 // const tickets4 = []; // 未購入の場合の定義例 const tickets4 = [['1234', 'straight'], ['5678', 'box'], ['9012', 'set']]; console.log('Numbers4 購入チケット:'); console.log(tickets4); // **************************************************************** // * Numbers3 定期購入チケット定義 // **************************************************************** // 購入番号と購入タイプを定義します。入力チェックはしていないので下記例を参考に正しく入力してください。 // const tickets4 = [['購入番号(999)','購入タイプ(straight/box/set/mini)'],['999','xxxx'],・・・]; // 定義方法 // const tickets3 = [['123', 'straight'], ['456', 'box'], ['789', 'set'], ['01', 'mini']]; // 定義例 // const tickets3 = []; // 未購入の場合の定義例 const tickets3 = [['123', 'straight'], ['456', 'box'], ['789', 'set'], ['01', 'mini']]; console.log('Numbers3 購入チケット:'); console.log(tickets3); // **************************************************************** // * 初期処理 // **************************************************************** console.log('====================== 初期処理'); const Obniz = require('obniz'); const obniz = new Obniz('OBNIZ_ID_HERE'); // Obniz ID を設定します。 const puppeteer = require('puppeteer'); let tosenTicketsCnt4 = 0; // Numbers4 当選チケット数 let tosenTicketsCnt3 = 0; // Numbers3 当選チケット数 // ******************************** // * メイン処理 // ******************************** console.log('====================== メイン処理'); obniz.onconnect = async function () { // **************************************************************** // みずほ銀行の当選番号案内サイトから直近の当選番号を取得する // **************************************************************** console.log('====================== みずほ銀行の当選番号案内サイトから直近の当選番号を取得する'); // Numbers4 当選情報をスクレイピング const browser4 = await puppeteer.launch(); const page_num4 = await browser4.newPage(); await page_num4.goto('https://www.mizuhobank.co.jp/retail/takarakuji/numbers/numbers4/index.html', { waitUntil: 'networkidle0' }); const tbl_num4 = await page_num4.$$('table.typeTK'); const d4 = await Promise.all(tbl_num4.map(async table4 => { const t4 = (await (await table4.getProperty('textContent')).jsonValue()).trim(); const ts4 = t4.split('\n'); return { kai: ts4[1], // 回別 date: ts4[7], // 抽せん日 number: ts4[11] // 抽せん数字 } })) const tosenKai4 = d4[0].kai; // 直近の回別 const tosenDate4 = d4[0].date; // 直近の抽せん日 const tosenNo4 = d4[0].number; // 直近の抽せん数字 // const tosenNo4 = '0001'; // 直近の抽せん数字 console.log('Numbers4 回別:' + tosenKai4 + ' 抽せん日:' + tosenDate4 + ' 抽せん数字:' + tosenNo4); await browser4.close(); // Numbers3 当選情報をスクレイピング const browser3 = await puppeteer.launch(); const page_num3 = await browser3.newPage(); await page_num3.goto('https://www.mizuhobank.co.jp/retail/takarakuji/numbers/numbers3/index.html', { waitUntil: 'networkidle0' }); const tbl_num3 = await page_num3.$$('table.typeTK'); const d3 = await Promise.all(tbl_num3.map(async table3 => { const t3 = (await (await table3.getProperty('textContent')).jsonValue()).trim(); const ts3 = t3.split('\n'); return { kai: ts3[1], // 回別 date: ts3[7], // 抽せん日 number: ts3[11] // 抽せん数字 } })) const tosenKai3 = d3[0].kai; // 直近の回別 const tosenDate3 = d3[0].date; // 直近の抽せん日 const tosenNo3 = d3[0].number; // 直近の抽せん数字 // const tosenNo3 = '002'; // 直近の抽せん数字 console.log('Numbers3 回別:' + tosenKai3 + ' 抽せん日:' + tosenDate3 + ' 抽せん数字:' + tosenNo3); await browser3.close(); // **************************************************************** // 当選判定 // **************************************************************** console.log('====================== 当選判定'); // Numbers4 当選判定 tickets4.forEach(function (value, index) { console.log('------------------'); const ticketsNo4 = value[0]; // 購入番号 const ticketsType4 = value[1]; // 購入タイプ console.log('Numbers4 Tickets[' + (index + 1) + ']購入番号:' + ticketsNo4 + ' 購入タイプ:' + ticketsType4); // ストレート当選権利判定(当選条件:数字と並びの順序が一致) let tosenStraightFlg4 = 0; // ストレート当選権利フラグ(0:権利なし、1:権利あり) if (tosenNo4 == ticketsNo4) { tosenStraightFlg4 = 1; } // ボックス当選権利判定(当選条件:数字が一致すれば並びの順序は異なってもよい) let tosenBoxFlg4 = 0; // ボックス当選権利フラグ(0:権利なし、1:権利あり) const tosenNoArray4 = Array.from(tosenNo4); const ticketsNoArray4 = Array.from(String(ticketsNo4)); ticketsNoArray4.forEach(function (valueTicketsNo4, indexTickesNo4) { const findTicketsNo4 = tosenNoArray4.indexOf(valueTicketsNo4); if (findTicketsNo4 !== -1) { tosenNoArray4.splice(findTicketsNo4, 1); } }) if (tosenNoArray4.length == 0) { tosenBoxFlg4 = 1; } // 当選判定 let tosenTickets4 = ''; // 購入タイプ = ストレート の場合 if (ticketsType4 == 'straight') { if (tosenStraightFlg4 == 1) { tosenTickets4 = 'straight'; tosenTicketsCnt4 ++; } // 購入タイプ = ボックス の場合 } else if (ticketsType4 == 'box') { if (tosenStraightFlg4 == 1) { tosenTickets4 = 'box'; tosenTicketsCnt4 ++; } else if (tosenBoxFlg4 == 1) { tosenTickets4 = 'box'; tosenTicketsCnt4 ++; } // 購入タイプ = セット の場合 } else if (ticketsType4 == 'set') { if (tosenStraightFlg4 == 1) { tosenTickets4 = 'set-straight'; tosenTicketsCnt4 ++; } else if (tosenBoxFlg4 == 1) { tosenTickets4 = 'set-box'; tosenTicketsCnt4 ++; } } console.log('Numbers4 当選結果:' + (tosenTickets4 == '' ? 'はずれ' : 'あたり:' + tosenTickets4)); }); // Numbers3 当選判定 tickets3.forEach(function (value, index) { console.log('------------------'); const ticketsNo3 = value[0]; // 購入番号 const ticketsType3 = value[1]; // 購入タイプ console.log('Numbers3 Tickets[' + (index + 1) + ']購入番号:' + ticketsNo3+ ' 購入タイプ:' + ticketsType3); // ストレート当選権利判定(当選条件:数字と並びの順序が一致) let tosenStraightFlg3 = 0; // ストレート当選権利フラグ(0:権利なし、1:権利あり) if (tosenNo3 == ticketsNo3) { tosenStraightFlg3 = 1; } // ボックス当選権利判定(当選条件:数字が一致すれば並びの順序は異なってもよい) let tosenBoxFlg3 = 0; // ボックス当選権利フラグ(0:権利なし、1:権利あり) const tosenNoArray3 = Array.from(tosenNo3); const ticketsNoArray3 = Array.from(String(ticketsNo3)); ticketsNoArray3.forEach(function (valueTicketsNo3, indexTickesNo3) { const findTicketsNo3 = tosenNoArray3.indexOf(valueTicketsNo3); if (findTicketsNo3 !== -1) { tosenNoArray3.splice(findTicketsNo3, 1); } }) if (tosenNoArray3.length == 0) { tosenBoxFlg3 = 1; } // ミニ当選権利判定(当選条件:下2ケタの数字と並びの順序が一致(ナンバーズ3のみ)) let tosenMiniFlg3 = 0; // ミニ当選権利フラグ(0:権利なし、1:権利あり) if (tosenNo3.substr(1, 2) == ticketsNo3) { tosenMiniFlg3 = 1; } // 当選判定 let tosenTickets3 = ''; // 購入タイプ = ストレート の場合 if (ticketsType3 == 'straight') { if (tosenStraightFlg3 == 1) { tosenTickets3 = 'straight'; tosenTicketsCnt3 ++; } // 購入タイプ = ボックス の場合 } else if (ticketsType3 == 'box') { if (tosenStraightFlg3 == 1) { tosenTickets3 = 'box'; tosenTicketsCnt3 ++; } else if (tosenBoxFlg3 == 1) { tosenTickets3 = 'box'; tosenTicketsCnt3 ++; } // 購入タイプ = セット の場合 } else if (ticketsType3 == 'set') { if (tosenStraightFlg3 == 1) { tosenTickets3 = 'set-straight'; tosenTicketsCnt3 ++; } else if (tosenBoxFlg3 == 1) { tosenTickets3 = 'set-box'; tosenTicketsCnt3 ++; } // 購入タイプ = ミニ の場合 } else if (ticketsType3 == 'mini') { if (tosenMiniFlg3 == 1) { tosenTickets3 = 'mini'; tosenTicketsCnt3 ++; } } console.log('Numbers3 当選結果:' + (tosenTickets3 == '' ? 'はずれ' : 'あたり:' + tosenTickets3)); }); // **************************************************************** // LED 点灯 // **************************************************************** console.log('====================== LED 点灯'); console.log('Numbers4 当選数:' + tosenTicketsCnt4); console.log('Numbers3 当選数:' + tosenTicketsCnt3); const led = obniz.wired('FullColorLED', { r: 8, g: 11, b: 10, common: 9, commonType: 'anode_common' }); if ((tosenTicketsCnt4 > 0) || (tosenTicketsCnt3 > 0)) { await led.gradation(200); // あたりの場合、グラデーション点灯 } else { await led.rgb(0, 0, 255); // はずれの場合、青色点灯 } // **************************************************************** // 当選番号の 7Seg 表示 // **************************************************************** console.log('====================== 当選番号の 7Seg 表示'); const segment = obniz.wired('7SegmentLED_MAX7219', { clk: 4, cs: 3, din: 2, gnd: 1, vcc: 0 }); await segment.init(1, 8); await segment.brightness(0, 5); // 明るさ(0 ~ 15) await segment.clearAll(); const tosenNoArray7seg4 = Array.from(tosenNo4); // Numbers4 当選番号を配列へ代入 const tosenNoArray7seg3 = Array.from(tosenNo3); // Numbers3 当選番号を配列へ代入 // 約10分間の表示 for (let i = 0; i < 1200; i++) { // 上4桁に Numbers4 当選番号表示 segment.setNumber(0, 7, tosenNoArray7seg4[0], false); segment.setNumber(0, 6, tosenNoArray7seg4[1], false); segment.setNumber(0, 5, tosenNoArray7seg4[2], false); segment.setNumber(0, 4, tosenNoArray7seg4[3], false); // 下3桁に Numbers3 当選番号表示 segment.setNumber(0, 3, 'off', false); segment.setNumber(0, 2, tosenNoArray7seg3[0], false); segment.setNumber(0, 1, tosenNoArray7seg3[1], false); segment.setNumber(0, 0, tosenNoArray7seg3[2], false); if ((i % 2 == 0) && (tosenTicketsCnt4 > 0)) { // 当選時に 上4桁 Numbers4 当選番号点滅 segment.setNumber(0, 7, 'off', false); segment.setNumber(0, 6, 'off', false); segment.setNumber(0, 5, 'off', false); segment.setNumber(0, 4, 'off', false); } if ((i % 2 == 0) && (tosenTicketsCnt3 > 0)) { // 当選時に 下3桁 Numbers3 当選番号点滅 segment.setNumber(0, 3, 'off', false); segment.setNumber(0, 2, 'off', false); segment.setNumber(0, 1, 'off', false); segment.setNumber(0, 0, 'off', false); } await obniz.wait(500); } // **************************************************************** // スリープ // **************************************************************** console.log('====================== スリープ'); // 現在日時を取得 const currentDatetime = new Date(); console.log('現在日時    :' + currentDatetime.toLocaleString()); // スリープ解除日時(翌日の20時の例) const sleepReleaseDatetime = new Date( currentDatetime.getFullYear(), // 年(yyyy) currentDatetime.getMonth(), // 月(mm) currentDatetime.getDate() + 1, // 日(dd) 20, // 時(hh) 0, // 分(mm) 0 // 秒(ss) ); console.log('スリープ解除日時:' + sleepReleaseDatetime.toLocaleString()); // スリープ解除までの時間を取得 const sleepTime = sleepReleaseDatetime.getTime() - currentDatetime.getTime(); const sleepTimeMinute = Math.floor(sleepTime / (60 * 1000)); console.log('スリープ時間:' + sleepTimeMinute + ' 分'); // スリープ obniz.sleepMinute(sleepTimeMinute); } ``` ### 実行ログイメージ ``` C:\obniz\numbers>node app.js Numbers4 購入チケット: [ [ '1234', 'straight' ], [ '5678', 'box' ], [ '9012', 'set' ], [ '9820', 'set' ] ] Numbers3 購入チケット: [ [ '001', 'straight' ], [ '456', 'box' ], [ '789', 'set' ], [ '01', 'mini' ] ] ====================== 初期処理 ====================== メイン処理 ====================== みずほ銀行の当選番号案内サイトから直近の当選番号を取得する Numbers4 回別:第5688回 抽せん日:2021年5月7日 抽せん数字:0982 Numbers3 回別:第5688回 抽せん日:2021年5月7日 抽せん数字:068 ====================== 当選判定 ------------------ Numbers4 Tickets[1]購入番号:1234 購入タイプ:straight Numbers4 当選結果:はずれ ------------------ Numbers4 Tickets[2]購入番号:5678 購入タイプ:box Numbers4 当選結果:はずれ ------------------ Numbers4 Tickets[3]購入番号:9012 購入タイプ:set Numbers4 当選結果:はずれ ------------------ Numbers4 Tickets[4]購入番号:9820 購入タイプ:set Numbers4 当選結果:あたり:set-box ------------------ Numbers3 Tickets[1]購入番号:001 購入タイプ:straight Numbers3 当選結果:はずれ ------------------ Numbers3 Tickets[2]購入番号:456 購入タイプ:box Numbers3 当選結果:はずれ ------------------ Numbers3 Tickets[3]購入番号:789 購入タイプ:set Numbers3 当選結果:はずれ ------------------ Numbers3 Tickets[4]購入番号:01 購入タイプ:mini Numbers3 当選結果:はずれ ====================== LED 点灯 Numbers4 当選数:1 Numbers3 当選数:0 ====================== 当選番号の 7Seg 表示 ====================== スリープ 現在日時    :2021/5/8 15:11:54 スリープ解除日時:2021/5/9 20:00:00 スリープ時間:1728 分 ``` # 感想 - ネットワークの問題だと思いますが、obnizとの接続が不安定だったりします。 - 7Seg表示やLED点灯のタイムラグが解決出来ませんでした。どうしたものか… - USB-Cケーブルがごつくて取り回しに苦労しました。極細極短極柔ケーブルが欲しい。L型コネクタってのも便利そう。自作出来るのかな? - Sleep機能を使うならモバイルバッテリー駆動にしたくてこだわりました。でもIoT機器に対応したモデルって少ないので入手に苦労しました。 # 参考サイト - obniz公式 [Node.jsで動かすには](https://obniz.com/ja/doc/guides/nodejs/how-to-run) - obniz公式 [7SegmentLED_MAX7219](https://obniz.com/ja/sdk/parts/7SegmentLED_MAX7219/README.md) - obniz公式 [FullcolorLED](https://obniz.com/ja/sdk/parts/FullcolorLED/README.md) - obniz公式 [スリープ](https://obniz.com/ja/doc/reference/common/sleep) - みずほ銀行 [当せん番号案内(ナンバーズ4)](https://www.mizuhobank.co.jp/retail/takarakuji/check/numbers/numbers4/index.html) - みずほ銀行 [当せん番号案内(ナンバーズ3)](https://www.mizuhobank.co.jp/retail/takarakuji/check/numbers/numbers3/index.html) - YouTube動画 [Puppeteerで宝くじのNumbersと競馬サイトをスクレイピング](https://www.youtube.com/watch?v=APuu-MIuPlA)