Node.js ist eine serverseitige Laufzeitumgebung, um Webanwendungen oder Webservices zu erstellen. Für das Erstellen von interaktiven Webseiten wird clientseitig JavaScript verwendet. Hieraus entstand die Idee, JavaScript auch für Serveranwendungen zu nutzen. Die Laufzeitumgebung ist die V8 Engine von Google. Das bedeutet, dass auf der IBM i die gleiche JavaScript Engine implementiert ist wie in Chrome, dem Browser von Google. Node.js ist seit Dezember 2014 für die IBM i kostenlos verfügbar.
Und so arbeitet die Anwendung: Ein RPG-Programm schreibt Daten für eine SMS in eine DataQueue im JSON-Format, und zwar den Text der SMS, die Telefonnummer des Empfängers und die Telefonnummer des Senders, was dann folgendermaßen aussieht:
{"body": "Hello", "to": "+123456789", "from": "+123456789"}
Ein Node.js-Programm „lauscht“ an der DataQueue, ob neue Daten vorhanden sind. Diese werden dann über die Twilio API als SMS versendet.
Der Versand von SMS-Daten über Twilio ist ein Beispiel. Mittlerweile verfügen allerdings viele SMS-Versender über Node.js APIs, die sehr einfach über den Node Package Manager heruntergeladen werden können. Auf diese Weise können Sie die Anwendung auch leicht auf andere Anbieter übertragen.
1. Systemvoraussetzungen
Hier finden Sie einen Einstieg in Node.js: Einstieg
Um Node.js zu installieren, benötigen Sie mindestens V7R1 und folgende Lizenzprogramme:
5770-SS1 Option 33 Portable App Solutions Environment 5733-SC1 Option 1 OpenSSH, OpenSSL, zlib 5770-DG1 *Base IBM HTTP-Server für i 5733-OPS Option 1 Node.js Runtime
Node.js ist ein kostenfreies Lizenzprogramm, das derzeit in drei Versionen auf der IBM i verfügbar ist:
5733-OPS Option 1 Node.js V0.x 5733-OPS Option 5 Node.js V4.x 5733-OPS Option 10 Node.js V6.x
Nach der Installation befindet sich Node.js in folgenden Verzeichnissen:
V0.x /QopenSys/QIBM/ProdData/Node V4.x /QopenSys/QIBM/ProdData/OPS/Node4 V6.x /QopenSys/QIBM/ProdData/OPS/Node6
Wenn Sie Node V4 oder V6 nutzen wollen, dann stellen Sie die Version über die Qshell ein:
V4: 5250> qsh $ /QOpenSys/QIBM/ProdData/OPS/Node4/bin/nodever.sh 4 Node.js v4 will now be used. V6: 5250> qsh $ /QOpenSys/QIBM/ProdData/OPS/Node6/bin/nodever.sh 6 Node.js v6 will now be used.
Jetzt können Sie prüfen, welche Version von Node.js und dem Node Package Manager eingestellt ist. Der Node Package Manager ist ein Dienstprogramm, um Open Source Software (derzeit 240.000 Pakete) zu installieren, zu aktualisieren und zu löschen (siehe www.npmjs.com).
5250> qsh $ node -v v6.9.1 $ npm -v 3.10.8
Die Twilio API installieren Sie mit dem Node Package Manager:
5250> qsh $ npm install twilio
Die API befindet sich nach der Installation im Verzeichnis /home/node_modules/twilio. Für die Authentifizierung benötigen Sie eine accountSid und den authToken. Sie erhalten diese nach Ihrer Registrierung unter www.twilio.com/console.
Für das Erzeugen der JSON-Daten ist derzeit das Open-Source-Serviceprogramm YAJL (Yet another JSON Library) von Scott Klement am besten geeignet. Sie können das Programm über folgenden Link kostenlos herunterladen: www.scottklement.com/yajl/
2. Die Komponenten der Anwendung
a) Erstellen der DataQueue mit einen CL-Programm
PGM CRTDTAQ DTAQ(MYLIB/SNDSMSQ) MAXLEN(5000) SEQ(*FIFO) + SIZE(*MAX2GB) AUTORCL(*YES) + TEXT('Dataqueue SMS Senden') AUT(*USE) ENDPGM
b) RPG-Programm zum Schreiben der Daten in die DataQueue. Die Daten werden im JSON-Format in die DataQueue geschrieben: {„body“: „Hello“, „to“: „+123456789“, „from“: „+123456789“}
Bei diesem Programm handelt es sich um ein „Mainline“-Programm. In den Ctl-Opt wird über Main(main) die Main-Prozedur aufgerufen. Ein *INLR ist nicht mehr notwendig. Weitere Informationen finden Sie unter Mcpressonline.com.
ctl-opt main(main) dftactgrp(*no) alloc(*teraspace) bnddir('YAJL'); //------------------------------------------------------------------// // // // Send JSON data to DataQueue // // // //----------------- // // R.Ross 10.2016 * // //------------------------------------------------------------------// // Prototypes // //------------------------------------------------------------------// /include json/qrpglesrc,yajl_h //------------------------------------------------------------------// // Send Data to DTAQ // //------------------------------------------------------------------// dcl-pr snddtaq extpgm('QSNDDTAQ'); ##dtqname like(d#dtqname) const; ##dtqlib like(d#dtqlib) const; ##dtqlength like(d#dtqlength) const; ##dtqdata char(32766) const options(*varsize); end-pr; //------------------------------------------------------------------// // Variablen für DTQ-API // //------------------------------------------------------------------// dcl-s d#dtqname char(10) inz('SNDSMSQ'); // DTQ-Name dcl-s d#dtqlib char(10) inz('MYLIB'); // DTQ-Lib dcl-s d#dtqlength packed(05) inz(%size(d#dtqdata)); // DTQ-Length dcl-s d#dtqwait packed(05) inz(-1); // DTQ-Wait dcl-s d#dtqdata char(5000); // DTQ-Data //------------------------------------------------------------------// // Variablen // //------------------------------------------------------------------// dcl-s body varchar(4000); // SMS-Body dcl-s to varchar(30); // SMS-To dcl-s from varchar(30); // SMS-From dcl-s jsondata varchar(5000); // JSON-Data dcl-s index uns(10); // Index //------------------------------------------------------------------// // Main // //------------------------------------------------------------------// dcl-proc main; for index = 1 to 5; // 5 Testdaten schreiben body = 'Hello Node ' + %char(index); to = '+4912345678'; from = '+4912345678'; d#dtqdata = crtjson(body:to:from); snddtaq(d#dtqname:d#dtqlib:d#dtqlength:d#dtqdata); endfor; snddtaq(d#dtqname:d#dtqlib:d#dtqlength:crtjson('*end':to:from)); end-proc; //------------------------------------------------------------------// // Procedure - create JSON data // //------------------------------------------------------------------// dcl-proc crtjson export; dcl-pi *n like(jsondata); // JSON-Data ##body like(body) const options(*varsize); ##to like(to) const options(*varsize); ##from like(from) const options(*varsize); end-pi; dcl-s p#size int(10) inz(%size(jsondata)); // JSON-length dcl-s p#len int(10); // Data-length dcl-s p#rc int(10); // ReturnCode dcl-s p#json_p pointer; // JSON-Pointer dcl-s p#jsondata like(jsondata); // JSON-Data dealloc(n) p#json_p; // JSON-Pointer p#json_p = %alloc(p#size); // Alloc Pointer yajl_genopen(*off); // *on = pretty Code yajl_beginobj(); yajl_addchar('body':##body); yajl_addchar('to' :##to); yajl_addchar('from':##from); yajl_endobj(); p#rc = yajl_copybuf(1141:p#json_p:p#size:p#len); // CCSID 1141 if p#rc = *zero and p#len > *zero; p#jsondata = %str(p#json_p:p#len); endif; yajl_genclose(); return p#jsondata; end-proc; //------------------------------------------------------------------//
c) Das Node.js-Programm nimmt die Daten aus der DataQueue entgegen, verarbeitet sie und wartet auf einen neuen Eintrag. Hierfür wird die QRCVDTAQ API benutzt. Das Skript befindet sich im IFS:
/QOpenSys/QIBM/ProdData/OPS/Node4/os400/xstoolkit/lib/idataq.js
In diesem Skript ist die Wait-Funktion auf einen neuen Eintrag nicht implementiert. Deshalb zeige ich Ihnen, wie Sie diese Funktion implementieren:
Das Originalskript kopieren und unter dem neuen Namen idataq2.js in das gleiche Verzeichnis einfügen.
Wenn Sie mit Node.js V4 arbeiten, lautet der Pfad:
/QOpenSys/QIBM/ProdData/OPS/Node4/os400/xstoolkit/lib/idataq2.js
Mit Node.js V6 lautet der Pfad:
/QOpenSys/QIBM/ProdData/OPS/Node6/os400/xstoolkit/lib/idataq2.js
Im Skript idataq2.js ändern Sie folgende Statements:
Zeile 70: iDataQueue.prototype.receiveFromDataQueue = function(name, lib, length, wait, cb) {
Zeile 76: pgm.addParam(wait, „5p0“);
d) Das Node.js-Programm sendSMSDataFromQueue.js. Sie erstellen unter dem Verzeichnis /home das Verzeichnis /node und hinterlegen hier das Skript sendSMSDataFromQueue.js.
var xt = require('/QOpenSys/QIBM/ProdData/OPS/Node4/os400/xstoolkit/lib/itoolkit'); var dq = require('/QOpenSys/QIBM/ProdData/OPS/Node4/os400/xstoolkit/lib/idataq2'); var twilio = require('twilio'); var accountSid = 'abcdefghijklmn'; // Account SID von der www.twilio.com/console var authToken = 'abcdefghijklmn'; // AuthToken von der www.twilio.com/console var conn = new xt.iConn('*LOCAL', 'User', 'Password'); // User und Password der IBM i var dtq = new dq.iDataQueue(conn); var client = new twilio.RestClient(accountSid, authToken); var data = ''; while (data.body !== '*end') { // Leseschleife auf die DataQueue data = JSON.parse(dtq.receiveFromDataQueue('SNDSMSQ', 'MYLIB', 5000, -1)); console.log('data: ' + JSON.stringify(data)); sendSMS(data); } function sendSMS(data) { client.messages.create({ body: data.body, // SMS body to: data.to, // SMS to number from: data.from // SMS from a valid Twilio number }, function(err, message) { if (err) { console.error(err.message); } }); }
e) Start des Node.js-Programms sendSMSDataFromQueue.js in der Qshell
5250> qsh node /home/node/sendSMSDataFromQueue.js
f) Aufruf des RPG-Programms mit Call. Das Programm schreibt nun fünf Test-SMS in die DataQueue. Das Node.js-Programm sendSMSDataFromQueue.js liest die Daten aus der Queue, protokolliert sie mit dem Befehl console.log und sendet sie an Twilio. Twilio versendet dann die SMS an den Empfänger.
Dieses Projekt finden Sie unter https://github.com/RainerRoss/Send-SMS-with-Twilio-from-IBM-i.
Viel Spaß beim Ausprobieren.