/** PIGPIO デーモンを Node.js から利用するモジュール ** */ /** 関数名・書式は Python Interface に準拠 ******************* */ #include #include #include #include using namespace Napi; // pigpio 初期化 Value _pigpioStart(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].IsString()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } std::string addrStr = info[0].As().Utf8Value(); std::string portStr = info[1].As().Utf8Value(); return Number::New(env, pigpio_start(addrStr.c_str(), portStr.c_str())); // return Number::New(env, pigpio_start(&addrStr[0], &portStr[0])); } // pigpio 後始末 Value _pigpioStop(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 pi = info[0].As().Int32Value(); pigpio_stop(pi); return env.Null(); } // GPIO 端子のモードを設定 Value _setMode(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()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int pi = info[0].As().Int32Value(); unsigned int gpio = info[1].As().Uint32Value(); unsigned int mode = info[2].As().Uint32Value(); return Number::New(env, set_mode(pi, gpio, mode)); } // GPIO 端子のモードを取得 // Value _GetMode(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(); // } // unsigned int gpio = info[0].As().DoubleValue(); // return Number::New(env, // get_mode(pi, gpio)); // } // GPIOの内部プルアップ/ダウン抵抗の設定/クリア Value _setPullUpDown(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()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int pi = info[0].As().Int32Value(); unsigned int gpio = info[1].As().Uint32Value(); unsigned int pud = info[2].As().Uint32Value(); return Number::New(env, set_pull_up_down(pi, gpio, pud)); } // 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 pi = info[0].As().Int32Value(); unsigned int gpio = info[1].As().Uint32Value(); return Number::New(env, gpio_read(pi, 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()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int pi = info[0].As().Int32Value(); unsigned int gpio = info[1].As().Uint32Value(); unsigned int value = info[2].As().Uint32Value(); return Number::New(env, gpio_write(pi, gpio, value)); } // サーボパルス幅をセットする Value _setServoPulsewidth(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 pi = info[0].As().Int32Value(); unsigned int user_gpio = info[1].As().Uint32Value(); unsigned int pulsewidth = info[2].As().Uint32Value(); return Number::New(env, set_servo_pulsewidth(pi, user_gpio, pulsewidth)); } // PWM周波数を設定する Value _setPwmFrequency(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 pi = info[0].As().Int32Value(); unsigned int user_gpio = info[1].As().Uint32Value(); unsigned int frequency = info[2].As().Uint32Value(); return Number::New(env, set_PWM_frequency(pi, user_gpio, frequency)); } // PWMのレンジを設定する // Value _SetPwmRange(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(); // } // unsigned int user_gpio = info[0].As().DoubleValue(); // unsigned int range = info[1].As().DoubleValue(); // return Number::New(env, // set_PWM_range(pi, user_gpio, range)); // } // PWMのデューティ比を指定して出力を開始する Value _setPwmDutycycle(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 pi = info[0].As().Int32Value(); unsigned int user_gpio = info[1].As().Uint32Value(); unsigned int dutycycle = info[2].As().Uint32Value(); return Number::New(env, set_PWM_dutycycle(pi, user_gpio, dutycycle)); } // シリアルポートを開く Value _serialOpen(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].IsString() || !info[2].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int pi = info[0].As().Int32Value(); std::string ser_tty = info[1].As().Utf8Value(); unsigned int baud = info[2].As().Uint32Value(); // &ser_tty[0] return Number::New(env, serial_open(pi, (char *)ser_tty.c_str(), baud, 0)); } // シリアルポートを閉じる Value _serialClose(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 pi = info[0].As().Int32Value(); unsigned int handle = info[1].As().Uint32Value(); return Number::New(env, serial_close(pi, handle)); } // シリアルデバイスからデータを読む Value _serialRead(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 pi = info[0].As().Int32Value(); unsigned int handle = info[1].As().Uint32Value(); unsigned int count = info[2].As().Uint32Value(); char buf[count]; int rxCount = serial_read(pi, handle, buf, count); auto outBuf = Buffer::Copy(env, buf, rxCount); return outBuf; } // シリアルデバイスにバイト列を書き込む(data: string) Value _serialWrite(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].IsBuffer()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int pi = info[0].As().Int32Value(); unsigned int handle = info[1].As().Uint32Value(); auto buf = info[2].As>(); int count = buf.Length(); return Number::New(env, serial_write(pi, handle, buf.Data(), count)); } // I2Cバスアドレスのデバイスのハンドルを返す Value _i2cOpen(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 pi = info[0].As().Int32Value(); unsigned int i2c_bus = info[1].As().Uint32Value(); unsigned int i2c_addr = info[2].As().Uint32Value(); return Number::New(env, i2c_open(pi, i2c_bus, i2c_addr, 0)); } // オープン済みI2Cハンドルを閉じる Value _i2cClose(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 pi = info[0].As().Int32Value(); unsigned int handle = info[1].As().Uint32Value(); return Number::New(env, i2c_close(pi, handle)); } // デバイスに1バイトを送る Value _i2cWriteByte(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 pi = info[0].As().Int32Value(); unsigned int handle = info[1].As().Uint32Value(); unsigned int bVal = info[2].As().Uint32Value(); return Number::New(env, i2c_write_byte(pi, handle, bVal)); } // デバイスから1バイトを受け取る Value _i2cReadByte(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[0].IsNumber()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int pi = info[0].As().Int32Value(); unsigned int handle = info[1].As().Uint32Value(); return Number::New(env, i2c_read_byte(pi, handle)); } // I2Cハンドルに関連付けられているデバイスの指定されたレジスタに1バイトを書き込む Value _i2cWriteByteData(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 pi = info[0].As().Int32Value(); unsigned int handle = info[1].As().Uint32Value(); unsigned int i2c_reg = info[2].As().Uint32Value(); unsigned int bVal = info[3].As().Uint32Value(); return Number::New(env, i2c_write_byte_data(pi, handle, i2c_reg, bVal)); } // I2Cハンドルに関連付けられているデバイスの指定されたレジスタから1バイトを読み込む Value _i2cReadByteData(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 pi = info[0].As().Int32Value(); unsigned int handle = info[1].As().Uint32Value(); unsigned int i2c_reg = info[2].As().Uint32Value(); return Number::New(env, i2c_read_byte_data(pi, handle, i2c_reg)); } // I2Cハンドルに関連付けられているデバイスの指定されたレジスタに最大32バイトのデータを書き込む。 Value _i2cWriteI2cBlockData(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].IsBuffer()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int pi = info[0].As().Int32Value(); unsigned int handle = info[1].As().Uint32Value(); unsigned int i2c_reg = info[2].As().Uint32Value(); auto buf = info[3].As>(); unsigned int count = buf.Length(); return Number::New(env, i2c_write_i2c_block_data(pi, handle, i2c_reg, buf.Data(), count)); } // I2Cハンドルに関連付けられているデバイスの指定されたレジスタからcountバイトを読み込む。countは1~32。 Value _i2cReadI2cBlockData(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 pi = info[0].As().Int32Value(); unsigned int handle = info[1].As().Uint32Value(); unsigned int i2cReg = info[2].As().Uint32Value(); unsigned int count = info[3].As().Uint32Value(); char buf[count]; int rxCount = i2c_read_i2c_block_data(pi, handle, i2cReg, buf, count); auto outBuf = Buffer::Copy(env, buf, rxCount); return outBuf; } // I2Cハンドルに関連付けられているデバイスの指定されたレジスタから単一の16ビットワードを読み取る Value _i2cReadWordData(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 pi = info[0].As().Int32Value(); unsigned int handle = info[1].As().Uint32Value(); unsigned int i2c_reg = info[2].As().Uint32Value(); return Number::New(env, i2c_read_word_data(pi, handle, i2c_reg)); } // i2c デバイスからデータを受け取る Value _i2cReadDevice(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 pi = info[0].As().Int32Value(); unsigned int handle = info[1].As().Uint32Value(); unsigned int count = info[2].As().Uint32Value(); char buf[count]; int rxCount = i2c_read_device(pi, handle, buf, count); auto outBuf = Buffer::Copy(env, buf, rxCount); return outBuf; } // i2c デバイスにバイト列を送る(data: buffer) Value _i2cWriteDevice(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].IsBuffer()) { TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); return env.Null(); } int pi = info[0].As().Int32Value(); unsigned int handle = info[1].As().Uint32Value(); auto buf = info[2].As>(); unsigned int count = buf.Length(); return Number::New(env, i2c_write_device(pi, handle, buf.Data(), count)); } Object Init(Env env, Object exports) { // exports.Set(String::New(env, "usleep"), Function::New(env, _Usleep)); exports.Set(String::New(env, "_pigpio_start"), Function::New(env, _pigpioStart)); exports.Set(String::New(env, "_pigpio_stop"), Function::New(env, _pigpioStop)); exports.Set(String::New(env, "_set_mode"), Function::New(env, _setMode)); // exports.Set(String::New(env, "get_mode"), Function::New(env, _GetMode)); 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_range"), Function::New(env, _SetPwmRange)); 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_device"), Function::New(env, _i2cWriteDevice)); exports.Set(String::New(env, "_i2c_read_device"), Function::New(env, _i2cReadDevice)); return exports; } NODE_API_MODULE(pigpio, Init)