[update] PNG 画像をファイルから読み込んでSSD1306ミニOLEDに表示するブロックを追加

develop
ocogeclub 2024-01-02 15:33:45 +09:00
parent ef353e0650
commit 8ac385c074
14 changed files with 2763 additions and 1397 deletions

1
.naverc Normal file
View File

@ -0,0 +1 @@
lts

View File

@ -8,8 +8,8 @@ const ugj_const = {
mascot_dirname: 'img',
mascot_defname: 'tamachee.png',
library_dirname: 'lib',
document_root: 'Documents',
tmp_dir: '.ocogeclub/tmp', //ホームディレクトリからのパス
document_root: 'ocogeclub/Docs', //ホームディレクトリからのパス
tmp_dir: 'ocogeclub/tmp', //ホームディレクトリからのパス
executable_path: 'ocogeclub/bin/', //ホームディレクトリからのパス
localStorage_fname: 'ocoge.json',
error_ja_all: 'エラーが発生しました。\n『おこげ倶楽部』までお問い合わせください。',
@ -314,6 +314,11 @@ class appTool {
return await this.ipcRenderer.invoke('text_to_rgba', text, font, color, start_x, start_y);
}
// メインプロセスpngjsPNG ファイル読み込み
async readPngFile(fname) {
return await this.ipcRenderer.invoke('read_png_file', fname);
}
}
// ブラウザ動作用
@ -347,8 +352,9 @@ class webTool {
let reader = new FileReader();
reader.readAsText(ev.target.files[0]);
reader.addEventListener('load', () => {
let xml = Blockly.Xml.textToDom(reader.result);
Blockly.Xml.domToWorkspace(xml, workspace);
// let xml = Blockly.Xml.textToDom(reader.result);
// Blockly.Xml.domToWorkspace(xml, workspace);
Blockly.Xml.domToWorkspace(Blockly.utils.xml.textToDom(reader.result), workspace);
});
});
fileInputEl.click();

View File

@ -2457,8 +2457,8 @@ javascript.javascriptGenerator.forBlock['ugj_blackboard_write'] = function (bloc
`}`,
`el.style.color = color;`,
`el.style.fontStyle = style;`,
// `el.innerHTML = ugj_htmlEntities(text);`,
`el.innerHTML = text;`,
`el.innerHTML = ugj_htmlEntities(text);`,
// `el.innerHTML = text;`,
`termEl.scrollTop = termEl.scrollHeight;`,
'}//#']
);

View File

@ -404,6 +404,47 @@ javascript.javascriptGenerator.forBlock['oc_oled_drawpixel'] = function (block,
var code = `${variable_oled_hand}.drawPixel([[${value_x}, ${value_y}, ${dropdown_color}]]);\n`;
return code;
};
/** PNG 画像をファイルから読み込んで描画 */
Blockly.defineBlocksWithJsonArray([{
"type": "oc_oled_readpngfile",
"message0": "%1 に PNG ファイル %2 を表示:始点 ( %3 , %4 )",
"args0": [
{
"type": "field_variable",
"name": "oled_hand",
"variable": "oled"
},
{
"type": "input_value",
"name": "fname",
"check": "String"
},
{
"type": "input_value",
"name": "x",
"check": "Number"
},
{
"type": "input_value",
"name": "y",
"check": "Number"
}
],
"inputsInline": true,
"previousStatement": null,
"nextStatement": null,
"style": "sensor_blocks",
"tooltip": "PNG ファイルを読み込んで OLED に表示します。「始点」は左上の座標です。",
"helpUrl": ""
}]);
javascript.javascriptGenerator.forBlock['oc_oled_readpngfile'] = function (block, generator) {
var variable_oled_hand = generator.nameDB_.getName(block.getFieldValue('oled_hand'), Blockly.Names.NameType.VARIABLE);
var value_fname = generator.valueToCode(block, 'fname', javascript.Order.ATOMIC);
var value_x = generator.valueToCode(block, 'x', javascript.Order.ATOMIC);
var value_y = generator.valueToCode(block, 'y', javascript.Order.ATOMIC);
var code = `${variable_oled_hand}.drawRGBAImage(await apptool.readPngFile(${value_fname}),${value_x},${value_y});\n`;
return code;
};
/********* */
/** Flyout */
@ -629,8 +670,61 @@ flyout_contents = flyout_contents.concat([
"color": "1"
}
},
{
"inputs": {
"type": "field_variable",
"name": "oled_hand",
"variable": "oled"
},
"inputs": {
"fname": {
"shadow": {
"fields": {
"TEXT": "/home/pi/1.png"
},
"type": "text"
}
},
"x": {
"shadow": {
"fields": {
"NUM": "0"
},
"type": "math_number"
}
},
"y": {
"shadow": {
"fields": {
"NUM": "0"
},
"type": "math_number"
}
}
},
"kind": "block",
"type": "oc_oled_readpngfile"
}
// {
// "inputs": {
// "type": "field_variable",
// "name": "oled_hand",
// "variable": "oled"
// },
// "inputs": {
// "fname": {
// "shadow": {
// "fields": {
// "TEXT": null
// },
// "type": "text"
// }
// }
// },
// "kind": "block",
// "type": "oc_oled_readpngfile"
// }
]);

View File

@ -354,11 +354,11 @@ div.toolbar-left {
div.toolbar-right {
position: absolute;
right: 2px;
right: 0px;
margin-top: 6px;
display: inline-block;
/* text-align: right; */
width: 500px;
width: 506px;
}
/* ツールバーボタン */

View File

@ -908,6 +908,7 @@
</block>
</value>
</block>
<block type="ugj_child_julius"></block>
<block type="aquestalk_pi">
<value name="talk">
<shadow type="text">

View File

@ -186,20 +186,6 @@ Blockly.registry.register(
Blockly.ToolboxCategory.registrationName,
CustomCategory, true);
// Always await function call
Blockly.JavaScript['procedures_callreturn'] = function (block) {
// Call a procedure with a return value.
var funcName = Blockly.JavaScript.variableDB_.getName(
block.getFieldValue('NAME'), Blockly.PROCEDURE_CATEGORY_NAME);
var args = [];
var variables = block.getVars();
for (var i = 0; i < variables.length; i++) {
args[i] = Blockly.JavaScript.valueToCode(block, 'ARG' + i,
Blockly.JavaScript.ORDER_NONE) || 'null';
}
var code = 'await ' + funcName + '(' + args.join(', ') + ')';
return [code, Blockly.JavaScript.ORDER_AWAIT];
};
//============ User Customize End ===============
@ -323,6 +309,21 @@ const ugj_loadWorkspace = () => {
}
}
// 関数呼び出しに await を挿入 Always await function call
javascript.javascriptGenerator.forBlock['procedures_callreturn'] = function (block, generator) {
// Call a procedure with a return value.
var funcName = generator.nameDB_.getName(
block.getFieldValue('NAME'), Blockly.PROCEDURE_CATEGORY_NAME);
var args = [];
var variables = block.getVars();
for (var i = 0; i < variables.length; i++) {
args[i] = generator.valueToCode(block, 'ARG' + i,
javascript.Order.NONE) || 'null';
}
var code = 'await ' + funcName + '(' + args.join(', ') + ')';
return [code, javascript.Order.AWAIT];
};
// コード生成
const ugj_generateCode = () => {
let code;

View File

@ -0,0 +1,12 @@
{
"targets": [
{
"target_name": "pigpio",
"sources": ["pigpio.cpp"],
"defines": ["NAPI_DISABLE_CPP_EXCEPTIONS"],
"include_dirs": ["<!@(node -p \"require( 'node-addon-api' ).include\")"],
"dependencies": ["<!(node -p \"require('node-addon-api').gyp\")"],
"libraries": ["-lpigpiod_if2", "-lrt"],
}
]
}

View File

@ -0,0 +1,104 @@
module.exports = require('bindings')('pigpio');
// module.exports.INPUT = 0;
// module.exports.OUTPUT = 1;
// module.exports.PUD_OFF = 0;
// module.exports.PUD_DOWN = 1;
// module.exports.PUD_UP = 2;
module.exports.SET_PULL_UP = 2;
module.exports.SET_PULL_DOWN = 1;
module.exports.SET_PULL_NONE = 0;
let pi = -1;
// let i2c_hand = -1;
// let ser_hand = -1;
module.exports.gpio_start = async (host = 'localhost', port = 8888, show_errors = true) => {
if (pi < 0) {
pi = await module.exports._gpiod_start(host, port.toString());
if (pi < 0) {
if (show_errors) console.log(pi);
}
}
return pi;
}
module.exports.gpio_stop = async () => {
if (pi >= 0) await module.exports._gpiod_stop(pi);
pi = -1;
}
module.exports.gpio_set_output = async gpio => {
if (pi >= 0) return await module.exports._set_mode(pi, gpio, 1);
}
module.exports.gpio_set_input = async (gpio, mode) => {
if (pi >= 0) {
let r = await module.exports._set_mode(pi, gpio, 0);
if (r == 0)
return await module.exports._set_pull_up_down(pi, gpio, mode);
else
return r;
}
}
module.exports.gpio_read = async gpio => {
if (pi >= 0) return await module.exports._gpio_read(pi, gpio);
}
module.exports.gpio_write = async (gpio, value) => {
if (pi >= 0) return await module.exports._gpio_write(pi, gpio, value);
}
module.exports.servo = async (gpio, pulse_width) => {
if (pi >= 0) return await module.exports._set_servo_pulsewidth(pi, gpio, pulse_width);
}
module.exports.pwm = async (gpio, pwm_frequency, pwm_duty_cycle) => {
if (pi >= 0) {
await module.exports._set_PWM_frequency(pi, gpio, pwm_frequency);
await module.exports._set_PWM_dutycycle(pi, gpio, pwm_duty_cycle);
}
}
module.exports.serial_open = async (tty, baud) => {
if (ser_hand >= 0) await module.exports._serial_close(pi, ser_hand); // 勝手に閉じる
ser_hand = await module.exports._serial_open(pi, tty, baud);
return ser_hand;
}
module.exports.serial_close = async () => {
if (ser_hand >= 0) await module.exports._serial_close(pi, ser_hand);
ser_hand = -1;
}
module.exports.serial_write = async data => {
if (ser_hand >= 0) return await module.exports._serial_write(pi, ser_hand, Buffer.from(data));
}
module.exports.serial_read = async count => {
if (ser_hand >= 0) return new TextDecoder().decode(await module.exports._serial_read(pi, ser_hand, count));
// if (ser_hand >= 0) return await module.exports._serial_read(pi, ser_hand, count);//.toString('utf8');
}
module.exports.i2c_open = async (i2c_bus, i2c_address) => {
if (i2c_hand >= 0) await module.exports._i2c_close(pi, i2c_hand); // 勝手に閉じる
i2c_hand = await module.exports._i2c_open(pi, i2c_bus, i2c_address);
return i2c_hand;
}
module.exports.i2c_close = async () => {
if (i2c_hand >= 0) await module.exports._i2c_close(pi, i2c_hand);
i2c_hand = -1;
}
module.exports.i2c_write_byte_data = async (reg, byte_val) => {
if (i2c_hand >= 0) return await module.exports._i2c_write_byte_data(pi, i2c_hand, reg, byte_val);
}
module.exports.i2c_read_byte_data = async reg => {
if (i2c_hand >= 0) return await module.exports._i2c_read_byte_data(pi, i2c_hand, reg);
}
module.exports.i2c_write_i2c_block_data = async (reg, data) => {
if (i2c_hand >= 0) return await module.exports._i2c_write_i2c_block_data(pi, i2c_hand, reg, Buffer.from(data));
}
module.exports.i2c_read_word_data = async reg => {
if (i2c_hand >= 0) return await module.exports._i2c_read_word_data(pi, i2c_hand, reg);
}
module.exports.i2c_read_device = async count => {
if (i2c_hand >= 0) return new TextDecoder().decode(await module.exports._i2c_read_device(pi, i2c_hand, count));
// if (i2c_hand >= 0) return await module.exports._i2c_read_device(pi, i2c_hand, count).toString('utf8');
}
module.exports.i2c_write_device = async data => {
if (i2c_hand >= 0) return await module.exports._i2c_write_device(pi, i2c_hand, Buffer.from(data));
}
// 終了処理
module.exports.close_all_handle = () => {
module.exports.serial_close();
module.exports.i2c_close();
module.exports.gpio_close();
}

View File

@ -0,0 +1,11 @@
{
"name": "@ocoge/pigpio",
"version": "0.0.1",
"main": "index.js",
"private": true,
"license": "MIT",
"dependencies": {
"bindings": "^1.5.0",
"node-addon-api": "^1.7.1"
}
}

View File

@ -0,0 +1,855 @@
/** PIGPIO デーモンを Node.js から利用するモジュール ** */
/** 関数名・書式は Python Interface に準拠 ******************* */
#include <napi.h>
#include <pigpiod_if2.h>
#include <unistd.h>
#include <string>
using namespace Napi;
// pigpio デーモンに接続
Promise _pigpioStart(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 2)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _pigpioStart").Value());
}
else if (!info[0].IsString() || !info[1].IsString())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _pigpioStart").Value());
}
else
{
std::string addrStr = info[0].As<String>().Utf8Value();
std::string portStr = info[1].As<String>().Utf8Value();
deferred.Resolve(Number::New(env, pigpio_start(addrStr.c_str(), portStr.c_str())));
}
return deferred.Promise();
}
// pigpio デーモンとの接続を閉じる
Promise _pigpioStop(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 1)
{
deferred.Reject(
TypeError::New(env, "IInvalid argument count: _pigpioStop").Value());
}
else if (!info[0].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid aargument types: _pigpioStop").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
pigpio_stop(pi);
deferred.Resolve(env.Null());
}
return deferred.Promise();
}
// GPIO 端子のモードを設定
Promise _setMode(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 3)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _setMode").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _setMode").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned gpio = info[1].As<Number>().Uint32Value();
unsigned mode = info[2].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, set_mode(pi, gpio, mode)));
}
return deferred.Promise();
}
// GPIOの内部プルアップ/ダウン抵抗の設定/クリア
Promise _setPullUpDown(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 3)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _setPullUpDown").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _setPullUpDown").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned gpio = info[1].As<Number>().Uint32Value();
unsigned pud = info[2].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, set_pull_up_down(pi, gpio, pud)));
}
return deferred.Promise();
}
// GPIOの電圧を読む
Promise _gpioRead(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 2)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _gpioRead").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _gpioRead").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned gpio = info[1].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, gpio_read(pi, gpio)));
}
return deferred.Promise();
}
// GPIO の電圧をセットする
Promise _gpioWrite(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 3)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _gpioWrite").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _gpioWrite").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned gpio = info[1].As<Number>().Uint32Value();
unsigned value = info[2].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, gpio_write(pi, gpio, value)));
}
return deferred.Promise();
}
// サーボパルス幅をセットする
Promise _setServoPulsewidth(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 3)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _setServoPulsewidth").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _setServoPulsewidth").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned user_gpio = info[1].As<Number>().Uint32Value();
unsigned pulsewidth = info[2].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, set_servo_pulsewidth(pi, user_gpio, pulsewidth)));
}
return deferred.Promise();
}
// PWM周波数を設定する
Promise _setPwmFrequency(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 3)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _setPwmFrequency").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _setPwmFrequency").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned user_gpio = info[1].As<Number>().Uint32Value();
unsigned frequency = info[2].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, set_PWM_frequency(pi, user_gpio, frequency)));
}
return deferred.Promise();
}
// PWMのデューティ比を指定して出力を開始する
Promise _setPwmDutycycle(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 3)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _setPwmDutycycle").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _setPwmDutycycle").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned user_gpio = info[1].As<Number>().Uint32Value();
unsigned dutycycle = info[2].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, set_PWM_dutycycle(pi, user_gpio, dutycycle)));
}
return deferred.Promise();
}
// シリアルポートを開く
Promise _serialOpen(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 4)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _serialOpen").Value());
}
else if (!info[0].IsNumber() || !info[1].IsString() || !info[2].IsNumber() || !info[3].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _serialOpen").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
std::string ser_tty = info[1].As<String>().Utf8Value();
unsigned baud = info[2].As<Number>().Uint32Value();
unsigned ser_flags = info[3].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, serial_open(pi, (char *)ser_tty.c_str(), baud, ser_flags)));
}
return deferred.Promise();
}
// シリアルポートを閉じる
Promise _serialClose(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 2)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _serialClose").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _serialClose").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, serial_close(pi, handle)));
}
return deferred.Promise();
}
// シリアルデバイスからデータを読む
Promise _serialRead(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 3)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _serialRead").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _serialRead").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
unsigned count = info[2].As<Number>().Uint32Value();
char buf[count];
int rxCount = serial_read(pi, handle, buf, count);
auto outBuf = Buffer<char>::Copy(env, buf, rxCount);
deferred.Resolve(outBuf);
}
return deferred.Promise();
}
// シリアルデバイスにバイト列を書き込む(data: string)
Promise _serialWrite(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 3)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _serialWrite").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsBuffer())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _serialWrite").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
auto buf = info[2].As<Buffer<char>>();
int count = buf.Length();
deferred.Resolve(Number::New(env, serial_write(pi, handle, buf.Data(), count)));
}
return deferred.Promise();
}
// シリアルデバイスから読み出し可能なバイト数を返す
Promise _serialDataAvailable(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 2)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _serialDataAvailable").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _serialDataAvailable").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, serial_data_available(pi, handle)));
}
return deferred.Promise();
}
// I2Cバスアドレスのデバイスのハンドルを返す
Promise _i2cOpen(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 4)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _i2cOpen").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber() || !info[3].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _i2cOpen").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned i2c_bus = info[1].As<Number>().Uint32Value();
unsigned i2c_addr = info[2].As<Number>().Uint32Value();
unsigned i2c_flags = info[3].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, i2c_open(pi, i2c_bus, i2c_addr, i2c_flags)));
}
return deferred.Promise();
}
// オープン済みI2Cハンドルを閉じる
Promise _i2cClose(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 2)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _i2cClose").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _i2cClose").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, i2c_close(pi, handle)));
}
return deferred.Promise();
}
// デバイスに1バイトを送る
Promise _i2cWriteByte(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 3)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _i2cWriteByte").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _i2cWriteByte").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
unsigned bVal = info[2].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, i2c_write_byte(pi, handle, bVal)));
}
return deferred.Promise();
}
// デバイスから1バイトを受け取る
Promise _i2cReadByte(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 2)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _i2cReadByte").Value());
}
else if (!info[0].IsNumber() || !info[0].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _i2cReadByte").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, i2c_read_byte(pi, handle)));
}
return deferred.Promise();
}
// I2Cハンドルに関連付けられているデバイスの指定されたレジスタに1バイトを書き込む
Promise _i2cWriteByteData(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 4)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _i2cWriteByteData").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber() || !info[3].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _i2cWriteByteData").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
unsigned i2c_reg = info[2].As<Number>().Uint32Value();
unsigned bVal = info[3].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, i2c_write_byte_data(pi, handle, i2c_reg, bVal)));
}
return deferred.Promise();
}
// I2Cハンドルに関連付けられているデバイスの指定されたレジスタから1バイトを読み込む
Promise _i2cReadByteData(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 3)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _i2cReadByteData").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _i2cReadByteData").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
unsigned i2c_reg = info[2].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, i2c_read_byte_data(pi, handle, i2c_reg)));
}
return deferred.Promise();
}
// I2Cハンドルに関連付けられているデバイスの指定されたレジスタからcountバイトを読み込む。countは132。
Promise _i2cReadI2cBlockData(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 4)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _i2cReadI2cBlockData").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber() || !info[3].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _i2cReadI2cBlockData").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
unsigned i2cReg = info[2].As<Number>().Uint32Value();
unsigned count = info[3].As<Number>().Uint32Value();
char buf[count];
int rxCount = i2c_read_i2c_block_data(pi, handle, i2cReg, buf, count);
auto outBuf = Buffer<char>::Copy(env, buf, rxCount);
deferred.Resolve(outBuf);
}
return deferred.Promise();
}
// I2Cハンドルに関連付けられているデバイスの指定されたレジスタに最大バイトのデータを書き込む。
Promise _i2cWriteI2cBlockData(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 5)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _i2cWriteI2cBlockData").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber() || !info[3].IsBuffer() || !info[4].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _i2cWriteI2cBlockData").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
unsigned i2c_reg = info[2].As<Number>().Uint32Value();
auto buf = info[3].As<Buffer<char>>();
unsigned count = info[4].As<Number>().Uint32Value();
// if (count < 0)
// count = buf.Length();
deferred.Resolve(Number::New(env, i2c_write_i2c_block_data(pi, handle, i2c_reg, buf.Data(), count)));
}
return deferred.Promise();
}
// I2Cハンドルに関連付けられているデバイスの指定されたレジスタから単一の16ビットワードを読み取る
Promise _i2cReadWordData(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 3)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _i2cReadWordData").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _i2cReadWordData").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
unsigned i2c_reg = info[2].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, i2c_read_word_data(pi, handle, i2c_reg)));
}
return deferred.Promise();
}
// I2Cハンドルに関連付けられているデバイスの指定されたレジスタに単一の16ビットワードを書き込む
Promise _i2cWriteWordData(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 4)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _i2cWriteWordData").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber() || !info[3].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _i2cWriteWordData").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
unsigned i2c_reg = info[2].As<Number>().Uint32Value();
unsigned wVal = info[3].As<Number>().Uint32Value();
deferred.Resolve(Number::New(env, i2c_write_word_data(pi, handle, i2c_reg, wVal)));
}
return deferred.Promise();
}
// i2c デバイスからデータを受け取る
Promise _i2cReadDevice(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 3)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _i2cReadDevice").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _i2cReadDevice").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
unsigned count = info[2].As<Number>().Uint32Value();
char buf[count];
int rxCount = i2c_read_device(pi, handle, buf, count);
auto outBuf = Buffer<char>::Copy(env, buf, rxCount);
deferred.Resolve(outBuf);
}
return deferred.Promise();
}
// i2c デバイスにバイト列を送る(data: buffer)
Promise _i2cWriteDevice(const CallbackInfo &info)
{
Env env = info.Env();
auto deferred = Napi::Promise::Deferred::New(env);
if (info.Length() != 4)
{
deferred.Reject(
TypeError::New(env, "Invalid argument count: _i2cWriteDevice").Value());
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsBuffer() || !info[3].IsNumber())
{
deferred.Reject(
Napi::TypeError::New(env, "Invalid argument types: _i2cWriteDevice").Value());
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
auto buf = info[2].As<Buffer<char>>();
unsigned count = info[3].As<Number>().Uint32Value();
// if (count < 0)
// count = buf.Length();
deferred.Resolve(Number::New(env, i2c_write_device(pi, handle, buf.Data(), count)));
}
return deferred.Promise();
}
/******** 同期処理関数 ********/
// pigpio デーモンに接続
Value _pigpiodStartSync(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() != 2)
{
TypeError::New(env, "Invalid argument count: _pigpioStartSync")
.ThrowAsJavaScriptException();
return env.Null();
}
else if (!info[0].IsString() || !info[1].IsString())
{
TypeError::New(env, "Invalid argument types: _pigpioStartSync").ThrowAsJavaScriptException();
return env.Null();
}
else
{
std::string ipaddr = info[0].As<String>().Utf8Value();
std::string port = info[1].As<String>().Utf8Value();
return Number::New(env, pigpio_start(addrStr.c_str(), portStr.c_str()));
}
}
// pigpio デーモンとの接続を閉じる
Value _pigpioStopSync(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() != 1)
{
TypeError::New(env, "Invalid argument count: _pigpioStopSync")
.ThrowAsJavaScriptException();
return env.Null();
}
else if (!info[0].IsNumber())
{
TypeError::New(env, "Invalid argument types: _pigpioStop")
.ThrowAsJavaScriptException();
return env.Null();
}
else
{
int sbc = info[0].As<Number>().Int32Value();
pigpio_stop(pi);
return env.Null();
}
}
// I2Cバスアドレスのデバイスのハンドルを返す
Value _i2cOpenSync(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() != 4)
{
TypeError::New(env, "Invalid argument count: _i2cOpen")
.ThrowAsJavaScriptException();
return env.Null();
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber() || !info[3].IsNumber())
{
TypeError::New(env, "Invalid argument types: _i2cOpen")
.ThrowAsJavaScriptException();
return env.Null();
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned i2c_bus = info[1].As<Number>().Uint32Value();
unsigned i2c_addr = info[2].As<Number>().Uint32Value();
unsigned i2c_flags = info[3].As<Number>().Uint32Value();
return Number::New(env, i2c_open(pi, i2c_bus, i2c_addr, i2c_flags));
}
}
// オープン済みI2Cハンドルを閉じる
Value _i2cCloseSync(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() != 2)
{
TypeError::New(env, "Invalid argument count: _i2cClose")
.ThrowAsJavaScriptException();
return env.Null();
}
else if (!info[0].IsNumber() || !info[1].IsNumber())
{
TypeError::New(env, "Invalid argument types: _i2cClose")
.ThrowAsJavaScriptException();
return env.Null();
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
return Number::New(env, i2c_close(pi, handle));
}
}
// デバイスから1バイトを受け取る
Value _i2cReadByteSync(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() != 2)
{
TypeError::New(env, "Invalid argument count: _i2cReadByteSync")
.ThrowAsJavaScriptException();
return env.Null();
}
else if (!info[0].IsNumber() || !info[0].IsNumber())
{
TypeError::New(env, "Invalid argument types: _i2cReadByteSync")
.ThrowAsJavaScriptException();
return env.Null();
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
return Number::New(env, i2c_read_byte(pi, handle));
}
}
// i2c デバイスにバイト列を送る(data: buffer)
Value _i2cWriteDeviceSync(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() != 4)
{
TypeError::New(env, "Invalid argument count: _i2cWriteDevice")
.ThrowAsJavaScriptException();
return env.Null();
}
else if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsBuffer() || !info[3].IsNumber())
{
TypeError::New(env, "Invalid argument types: _i2cWriteDevice")
.ThrowAsJavaScriptException();
return env.Null();
}
else
{
int pi = info[0].As<Number>().Int32Value();
unsigned handle = info[1].As<Number>().Uint32Value();
auto buf = info[2].As<Buffer<char>>();
unsigned count = info[3].As<Number>().Uint32Value();
return Number::New(env, i2c_write_device(pi, handle, buf.Data(), count));
}
}
Object
Init(Env env, Object exports)
{
exports.Set(String::New(env, "_gpiod_start"), Function::New(env, _pigpioStart));
exports.Set(String::New(env, "_gpiod_stop"), Function::New(env, _pigpioStop));
exports.Set(String::New(env, "_set_mode"), Function::New(env, _setMode));
exports.Set(String::New(env, "_set_pull_up_down"), Function::New(env, _setPullUpDown));
exports.Set(String::New(env, "_gpio_read"), Function::New(env, _gpioRead));
exports.Set(String::New(env, "_gpio_write"), Function::New(env, _gpioWrite));
exports.Set(String::New(env, "_set_servo_pulsewidth"), Function::New(env, _setServoPulsewidth));
exports.Set(String::New(env, "_set_PWM_frequency"), Function::New(env, _setPwmFrequency));
exports.Set(String::New(env, "_set_PWM_dutycycle"), Function::New(env, _setPwmDutycycle));
exports.Set(String::New(env, "_serial_open"), Function::New(env, _serialOpen));
exports.Set(String::New(env, "_serial_close"), Function::New(env, _serialClose));
exports.Set(String::New(env, "_serial_read"), Function::New(env, _serialRead));
exports.Set(String::New(env, "_serial_write"), Function::New(env, _serialWrite));
exports.Set(String::New(env, "_i2c_open"), Function::New(env, _i2cOpen));
exports.Set(String::New(env, "_i2c_close"), Function::New(env, _i2cClose));
exports.Set(String::New(env, "_i2c_write_byte"), Function::New(env, _i2cWriteByte));
exports.Set(String::New(env, "_i2c_read_byte"), Function::New(env, _i2cReadByte));
exports.Set(String::New(env, "_i2c_write_byte_data"), Function::New(env, _i2cWriteByteData));
exports.Set(String::New(env, "_i2c_read_byte_data"), Function::New(env, _i2cReadByteData));
exports.Set(String::New(env, "_i2c_write_i2c_block_data"), Function::New(env, _i2cWriteI2cBlockData));
exports.Set(String::New(env, "_i2c_read_i2c_block_data"), Function::New(env, _i2cReadI2cBlockData));
exports.Set(String::New(env, "_i2c_read_word_data"), Function::New(env, _i2cReadWordData));
exports.Set(String::New(env, "_i2c_write_word_data"), Function::New(env, _i2cWriteWordData));
exports.Set(String::New(env, "_i2c_write_device"), Function::New(env, _i2cWriteDevice));
exports.Set(String::New(env, "_i2c_read_device"), Function::New(env, _i2cReadDevice));
return exports;
}
NODE_API_MODULE(pigpio, Init)

View File

@ -314,3 +314,8 @@ ipcMain.handle('text_to_rgba', (ev, text, font, color, start_x, start_y) => {
ctx.fillText(text, start_x, start_y);
return PNG.sync.read(canvas.toBuffer());
})
// Read PNG File : Returns PNG buffer data
ipcMain.handle('read_png_file', (ev, fname) => {
const data = fs.readFileSync(fname);
return PNG.sync.read(data);
})

2996
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "ocoge",
"version": "0.1.11",
"version": "0.1.12",
"description": "ブロックベースビジュアルプログラム開発・実行環境",
"main": "main.js",
"scripts": {
@ -22,31 +22,29 @@
},
"homepage": "https://git.ocoge.club/ocoge.club/ocoge#readme",
"devDependencies": {
"@electron-forge/cli": "^6.3.0",
"@electron-forge/maker-deb": "^6.3.0",
"@electron/rebuild": "^3.2.13",
"electron": "^26.0.0"
"@electron-forge/cli": "^7.2.0",
"@electron-forge/maker-deb": "^7.2.0",
"@electron/rebuild": "^3.4.1",
"electron": "^28.1.0"
},
"dependencies": {
"@blockly/field-slider": "^6.0.3",
"@napi-rs/canvas": "^0.1.43",
"@blockly/field-slider": "^6.1.4",
"@ocoge/amg8833": "file:local_modules/amg8833",
"@ocoge/bme280": "file:local_modules/bme280",
"@ocoge/paj7620": "file:local_modules/paj7620",
"@ocoge/ssd1306": "file:local_modules/ssd1306",
"@tensorflow-models/blazeface": "^0.1.0",
"@tensorflow-models/knn-classifier": "^1.2.5",
"@tensorflow-models/knn-classifier": "^1.2.6",
"@tensorflow-models/mobilenet": "^2.1.1",
"@tensorflow-models/speech-commands": "^0.5.4",
"@tensorflow/tfjs-node": "^4.10.0",
"amg8833": "file:local_modules/amg8833",
"axios": "^1.4.0",
"blockly": "^10.1.2",
"@tensorflow/tfjs-node": "^4.15.0",
"axios": "^1.6.3",
"blockly": "^10.3.0",
"canvas": "^2.11.2",
"dracula-prism": "^2.1.13",
"js-beautify": "^1.14.9",
"node-abi": "^3.47.0",
"nodemailer": "^6.9.4",
"js-beautify": "^1.14.11",
"node-abi": "^3.52.0",
"nodemailer": "^6.9.8",
"oled-font-pack": "^1.0.1",
"pngjs": "^7.0.0",
"prismjs": "^1.29.0"