/** lgpio を Node.js から利用するモジュール ** */ /** 関数名・書式は lgpio Python に準拠 ******************* */ #include #include #include #include using namespace Napi; // gpiochipデバイスを開く Value gpiochipOpen(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 1) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int gpioDev = info[0].As().Int32Value(); return Number::New(env, lgGpiochipOpen(gpioDev)); } // gpiochipデバイスを閉じる Value gpiochipClose(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 1) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); return Number::New(env, lgGpiochipClose(handle)); } // GPIO のモードを出力にする(ことを要求?) Value gpioClaimOutput(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 2) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); int gpio = info[1].As().Int32Value(); return Number::New(env, lgGpioClaimOutput(handle, 0, gpio, 0)); } // GPIO のモードを入力にする(ことを要求?) Value gpioClaimInput(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 3) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); int gpio = info[1].As().Int32Value(); int lflag = info[2].As().Int32Value(); return Number::New(env, lgGpioClaimInput(handle, lflag, gpio)); } // GPIOの電圧を読む Value gpioRead(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 2) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); int gpio = info[1].As().Int32Value(); return Number::New(env, lgGpioRead(handle, gpio)); } // GPIO の電圧をセットする Value gpioWrite(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 3) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); int gpio = info[1].As().Int32Value(); int level = info[2].As().Int32Value(); return Number::New(env, lgGpioWrite(handle, gpio, level)); } // サーボパルス幅をセットする Value txServo(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 3) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); int gpio = info[1].As().Int32Value(); int pulseWidth = info[2].As().Int32Value(); return Number::New(env, lgTxServo(handle, gpio, pulseWidth, 50, 0, 0)); } // PWMを設定して出力 Value txPwm(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 4) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber() || !info[3].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); int gpio = info[1].As().Int32Value(); float pwmFrequency = info[2].As().FloatValue(); float pwmDutyCycle = info[3].As().FloatValue(); return Number::New(env, lgTxPwm(handle, gpio, pwmFrequency, pwmDutyCycle, 0, 0)); } // シリアルポートを開く Value serialOpen(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 2) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsString() || !info[1].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } std::string tty = info[0].As().Utf8Value(); // char *c = new char[tty.size()+1]; // std::strcpy(c, tty.c_str()); // &ser_tty[0] で参照できるらしいけど危険? int baud = info[1].As().Int32Value(); return Number::New(env, lgSerialOpen(tty.c_str(), baud, 0)); } // シリアルポートを閉じる Value serialClose(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 1) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); return Number::New(env, lgSerialClose(handle)); } // シリアルデバイスからデータを受け取る Value SerialRead(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 2) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); int count = info[1].As().Int32Value(); // char rxBuf[count + 1]; // int32_t resultCount = lgSerialRead(handle, rxBuf, count); // Buffer resultBuf = Buffer::Copy(env, rxBuf, count); auto rxBuf = Buffer::New(env, count); int rxCount = lgSerialRead(handle, rxBuf.Data(), count); Array returnArr = Array::New(env); int i = 0; returnArr[i] = Number::New(env, rxCount); returnArr[++i] = rxBuf; return returnArr; } // シリアルデバイスにバイト列を送る(data: buffer) Value serialWrite(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 2) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsBuffer()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); auto txBuf = info[1].As>(); int count = txBuf.Length(); return Number::New(env, lgSerialWrite(handle, txBuf.Data(), count)); } // I2Cバスアドレスのデバイスのハンドルを返す Value i2cOpen(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 2) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int i2cDev = info[0].As().Int32Value(); int i2cAddr = info[1].As().Int32Value(); return Number::New(env, lgI2cOpen(i2cDev, i2cAddr, 0)); } // オープン済みI2Cハンドルを閉じる Value i2cClose(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 1) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); return Number::New(env, lgI2cClose(handle)); } // デバイスに1バイトを送る Value i2cWriteByte(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 2) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); int byteVal = info[1].As().Int32Value(); return Number::New(env, lgI2cWriteByte(handle, byteVal)); } // デバイスから1バイトを受け取る Value i2cReadByte(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 1) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); return Number::New(env, lgI2cReadByte(handle)); } // I2Cハンドルに関連付けられているデバイスの指定されたレジスタに1バイトを書き込む Value i2cWriteByteData(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 3) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); int i2cReg = info[1].As().Int32Value(); int byteVal = info[2].As().Int32Value(); return Number::New(env, lgI2cWriteByteData(handle, i2cReg, byteVal)); } // I2Cハンドルに関連付けられているデバイスの指定されたレジスタから1バイトを読み込む Value i2cReadByteData(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 2) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); int i2cReg = info[1].As().Int32Value(); return Number::New(env, lgI2cReadByteData(handle, i2cReg)); } // I2Cハンドルに関連付けられているデバイスの指定されたレジスタからcountバイトを読み込む。countは1~32。 Value i2cReadI2cBlockData(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 3) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); int i2cReg = info[1].As().Int32Value(); int count = info[2].As().Int32Value(); auto rxBuf = Buffer::New(env, count); int rxCount = lgI2cReadI2CBlockData(handle, i2cReg, rxBuf.Data(), count); Array returnArr = Array::New(env); int i = 0; returnArr[i] = Number::New(env, rxCount); returnArr[++i] = rxBuf; return returnArr; } // I2Cハンドルに関連付けられているデバイスの指定されたレジスタから単一の16ビットワードを読み取る Value I2cReadWordData(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 2) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); int i2cReg = info[1].As().Int32Value(); return Number::New(env, lgI2cReadWordData(handle, i2cReg)); } // i2c デバイスからデータを受け取る Value I2cReadDevice(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 2) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); int count = info[1].As().Int32Value(); auto rxBuf = Buffer::New(env, count); int rxCount = lgI2cReadDevice(handle, rxBuf.Data(), count); auto returnArr = Array::New(env); int i = 0; returnArr[i] = Number::New(env, rxCount); returnArr[++i] = rxBuf; return returnArr; } // i2c デバイスにバイト列を送る(data: buffer) Value I2cWriteDevice(const CallbackInfo &info) { Env env = info.Env(); if (info.Length() < 2) { TypeError::New(env, "Wrong number of arguments") .ThrowAsJavaScriptException(); return env.Null(); } if (!info[0].IsNumber() || !info[1].IsBuffer()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int handle = info[0].As().Int32Value(); auto txBuf = info[1].As>(); int count = txBuf.Length(); return Number::New(env, lgI2cWriteDevice(handle, txBuf.Data(), count)); } Object Init(Env env, Object exports) { exports.Set(String::New(env, "gpiochip_open"), Function::New(env, gpiochipOpen)); exports.Set(String::New(env, "gpiochip_close"), Function::New(env, gpiochipClose)); exports.Set(String::New(env, "gpio_claim_input"), Function::New(env, gpioClaimInput)); exports.Set(String::New(env, "gpio_claim_output"), Function::New(env, gpioClaimOutput)); 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, "tx_servo"), Function::New(env, txServo)); exports.Set(String::New(env, "tx_pwm"), Function::New(env, txPwm)); 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_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_read_device"), Function::New(env, I2cReadDevice)); exports.Set(String::New(env, "i2c_write_device"), Function::New(env, I2cWriteDevice)); return exports; } NODE_API_MODULE(lgpio, Init)