From af9caac9e5a479e6b9e48160d67ecdca94202be1 Mon Sep 17 00:00:00 2001 From: Dominic Bosch Date: Wed, 23 Apr 2014 13:27:29 +0200 Subject: [PATCH] Implementation of more examples --- coffee/http-listener.coffee | 6 + examples/action-invokers/emailyak.coffee | 2 + .../neospeech.coffee | 10 +- examples/action-invokers/robert.coffee | 59 +++++++ examples/action-invokers/system.coffee | 13 ++ examples/event-pollers/continuously.coffee | 9 +- examples/event-pollers/importio.coffee | 69 ++++++-- examples/eventproducers/.gitignore | 1 + examples/eventproducers/hoststatistics.coffee | 67 ++++++++ .../handlers/remote-scripts/forge_module.html | 2 +- webpages/public/chart.html | 45 +++++ webpages/public/data/histochart.json | 157 ++++++++++++++++++ 12 files changed, 419 insertions(+), 21 deletions(-) rename examples/{event-pollers => action-invokers}/neospeech.coffee (94%) create mode 100644 examples/action-invokers/robert.coffee create mode 100644 examples/action-invokers/system.coffee create mode 100644 examples/eventproducers/.gitignore create mode 100644 examples/eventproducers/hoststatistics.coffee create mode 100644 webpages/public/chart.html create mode 100644 webpages/public/data/histochart.json diff --git a/coffee/http-listener.coffee b/coffee/http-listener.coffee index 43fb6fa..82f85b8 100644 --- a/coffee/http-listener.coffee +++ b/coffee/http-listener.coffee @@ -17,6 +17,8 @@ requestHandler = require './request-handler' # [querystring](http://nodejs.org/api/querystring.html) path = require 'path' qs = require 'querystring' +fs = require 'fs' +path = require 'path' # - External Modules: [express](http://expressjs.com/api.html) express = require 'express' @@ -63,6 +65,10 @@ activateWebHook = ( app, name ) => req.on 'end', -> indexEvent name, body, resp + # This is a hack to quickly allow storing of public accessible data + if name is 'uptimestatistics' + path = path.resolve __dirname, '..', 'webpages', 'public', 'data', 'histochart.json' + fs.writeFile pathUsers, JSON.stringify( body, undefined, 2 ), 'utf8', ( err ) -> ### Initializes the request routing and starts listening on the given port. diff --git a/examples/action-invokers/emailyak.coffee b/examples/action-invokers/emailyak.coffee index d868d92..9f4e6e6 100644 --- a/examples/action-invokers/emailyak.coffee +++ b/examples/action-invokers/emailyak.coffee @@ -32,6 +32,8 @@ Send a mail through Emailyak. @param content The content of the mail ### exports.sendMail = ( sender, receipient, subject, content ) -> + if typeof content isnt "string" + content = JSON.stringify content, undefined, 2 data = FromAddress: sender ToAddress: receipient diff --git a/examples/event-pollers/neospeech.coffee b/examples/action-invokers/neospeech.coffee similarity index 94% rename from examples/event-pollers/neospeech.coffee rename to examples/action-invokers/neospeech.coffee index 0356c39..ce854f5 100644 --- a/examples/event-pollers/neospeech.coffee +++ b/examples/action-invokers/neospeech.coffee @@ -59,7 +59,7 @@ parseAnswer = ( body ) -> # - idVoice: index of the voice used for conversion from the arrVoices array. # - idAudioFormat: index of the voice used for conversion from the arrVoices array. # - sampleRate: 8 or 16 kHz rate -exports.convertTextToSpeech = ( text, idVoice, idAudioFormat, sampleRate ) -> +exports.convertTextToSpeech = ( text, idVoice, idAudioFormat, sampleRate, infoEvent ) -> idVoice = parseInt( idVoice ) || 0 if idVoice > arrVoices.length - 1 or idVoice < 0 idVoice = 0 @@ -87,9 +87,9 @@ exports.convertTextToSpeech = ( text, idVoice, idAudioFormat, sampleRate ) -> oAnsw = parseAnswer body log 'Conversion order: ' + oAnsw.resultString if oAnsw.resultCode is '0' - pollUntilDone oAnsw.resultCode, params.emailaccount, params.accountid + pollUntilDone oAnsw.resultCode, params.emailaccount, params.accountid, infoEvent -pollUntilDone = ( conversionNumber, email, accountid ) -> +pollUntilDone = ( conversionNumber, email, accountid, infoEvent ) -> oPost = method: "GetConversionStatus" email: email @@ -101,11 +101,11 @@ pollUntilDone = ( conversionNumber, email, accountid ) -> if oAnsw.resultCode is '0' if oAnsw.statusCode is '4' or oAnsw.statusCode is '5' pushEvent - event: "NeospeechConversionCompleted" + event: infoEvent payload: accountid: accountid downloadUrl: oAnsw.downloadUrl else - pollUntilDone conversionNumber, email, accountid + pollUntilDone conversionNumber, email, accountid, infoEvent else log 'Request failed: ' + oAnsw.resultString diff --git a/examples/action-invokers/robert.coffee b/examples/action-invokers/robert.coffee new file mode 100644 index 0000000..2059b35 --- /dev/null +++ b/examples/action-invokers/robert.coffee @@ -0,0 +1,59 @@ + + +### +ProBinder ACTION INVOKER +------------------------ + +Global variables +This module requires user-specific parameters: +- username +- password +### +urlService = 'https://probinder.com/service/' +credentials = + username: params.username + password: params.password + +# +# The standard callback can be used if callback is not provided, e.g. if +# the function is called from outside +# +standardCallback = ( funcName ) -> + ( err, resp, body ) -> + if err + log "ERROR: During function '#{ funcName }'" + else + if resp.statusCode is 200 + log "Function '#{ funcName }' ran through without error" + else + log "ERROR: During function '#{ funcName }': #{ body.error.message }" + +### +Call the ProBinder service with the given parameters. + +@param {Object} args the required function arguments object +@param {Object} [args.data] the data to be posted +@param {String} args.service the required service identifier to be appended to the url +@param {String} args.method the required method identifier to be appended to the url +@param {function} [args.callback] the function to receive the request answer +### +callService = ( args ) -> + if not args.service or not args.method + log 'ERROR in call function: Missing arguments!' + else + if not args.callback + args.callback = standardCallback 'call' + url = urlService + args.service + '/' + args.method + needle.request 'post', url, args.data, credentials, args.callback + + +### +Does everything to post something in a binder + +@param {String} companyId the comany associated to the binder +@param {String} contextId the binder id +@param {String} content the content to be posted +### +exports.newStudent = ( obj ) -> + log 'Got new user object: ' + typeof obj + log JSON.stringify obj, undefined, 2 \ No newline at end of file diff --git a/examples/action-invokers/system.coffee b/examples/action-invokers/system.coffee new file mode 100644 index 0000000..a2a6061 --- /dev/null +++ b/examples/action-invokers/system.coffee @@ -0,0 +1,13 @@ + +# Helper constructs +# + +exports.parseTextToJSON = ( text, infoEvent ) -> + try + pushEvent + event: infoEvent + payload: JSON.parse text + log "Text successfully parsed" + catch e + log "Error during JSON parsing of #{ text }" + \ No newline at end of file diff --git a/examples/event-pollers/continuously.coffee b/examples/event-pollers/continuously.coffee index da209eb..092e2ca 100644 --- a/examples/event-pollers/continuously.coffee +++ b/examples/event-pollers/continuously.coffee @@ -1,6 +1,9 @@ # # Pushes an event into the system each time the function is polled # -exports.push = () -> - pushEvent - content: "This is an event that will be sent again and again every ten seconds" \ No newline at end of file + +# Requires the content to be posted +exports.push = ( content ) -> + log 'Posting event with content: ' + content + pushEvent + content: content \ No newline at end of file diff --git a/examples/event-pollers/importio.coffee b/examples/event-pollers/importio.coffee index 51ff6c3..0ac4656 100644 --- a/examples/event-pollers/importio.coffee +++ b/examples/event-pollers/importio.coffee @@ -1,14 +1,12 @@ ### -Import.io allows to capture data from the web -required module params: +Import.io allows to capture data from the web. +Here we grab prepared weather data from Meteoblue +Required module params: - apikey - userGuid ### -params.apikey = "Cc8AX35d4B89ozzmn5bpm7k70HRon5rrfUxZvOwkVRj31/oBGHzVfQSRp5mEvlOgxyh7xi+tFSL66iAFo1W/sQ==" -params.userGuid = "d19f0d08-bf73-4115-90a8-ac045ad4f225" - io = new importio params.userGuid, params.apikey, "query.import.io" tryToConnect = ( numAttempt, cb ) -> @@ -38,7 +36,7 @@ getCityUrl = ( idCity ) -> id = 0 arrPages[ id ] -queryService = ( inputParams ) -> +queryService = ( inputParams, cb ) -> tryToConnect 0, ( connected ) -> if not connected log 'ERROR: Cannot execute query because connection failed!' @@ -48,14 +46,15 @@ queryService = ( inputParams ) -> if msg.type is "MESSAGE" data = data.concat msg.data.results if finished - log JSON.stringify data - pushEvent data + log 'Successfully queried data' + cb data -exports.meteoblueWeekData = ( idCity ) -> +exports.weekData = ( idCity ) -> params = input: "webpage/url": getCityUrl idCity connectorGuids: [ "2a1d789a-4d24-4942-bdca-ffa0e9f99c85" ] - queryService params + queryService params, ( data ) -> + pushEvent data # [ # { # wind: '9 mph', @@ -69,11 +68,12 @@ exports.meteoblueWeekData = ( idCity ) -> # [...] # ] -exports.meteoblueCurrentData = ( idCity ) -> +exports.currentData = ( idCity ) -> params = input: "webpage/url": getCityUrl idCity connectorGuids: [ "06394265-b4e1-4b48-be82-a9f2acb9040f" ] - queryService params + queryService params, ( data ) -> + pushEvent data # [ # { # current_time_wind_desc: '01:00 | Overcast', @@ -82,3 +82,48 @@ exports.meteoblueCurrentData = ( idCity ) -> # city: 'Basel-Stadt' # } # ] + + +# Helper function to detect and convert temperatures +convertTemperature = ( text ) -> + arrStr = text.split '°' + if arrStr > 1 + val = parseFloat arrStr[ 0 ] + if arrStr[ 1 ] is 'F' + fahrenheit = val + celsius = ( fahrenheit - 32 ) * 5 / 9 + else if arrStr[ 1 ] is 'C' + celsius = val + fahrenheit = ( celsius * 9 / 5 ) + 32 + else + log "Unexpected temperature in #{ text }" + + celsius: celsius + fahrenheit: fahrenheit + kelvin: celsius - 273.15 + + +# idCity, the city identifier corresponding to the arrPages array +exports.temperature = ( idCity ) -> + params = + input: "webpage/url": getCityUrl idCity + connectorGuids: [ "06394265-b4e1-4b48-be82-a9f2acb9040f" ] + queryService params, ( data ) -> + pushEvent convertTemperature data[ 0 ].current_temp + + +# tempUnit: C, F or K for celsius, fahrenheit and kelvin +# the threshold above which we alert +# idCity, the city identifier corresponding to the arrPages array +exports.tempOverThreshold = ( tempUnit, tempThreshold, idCity ) -> + params = + input: "webpage/url": getCityUrl idCity + connectorGuids: [ "06394265-b4e1-4b48-be82-a9f2acb9040f" ] + queryService params, ( data ) -> + oTemp = convertTemperature data[ 0 ].current_temp + switch tempUnit + when "K" then val = oTemp.kelvin + when "F" then val = oTemp.fahrenheit + else val = oTemp.celsius + if val > parseFloat tempThreshold + pushEvent oTemp \ No newline at end of file diff --git a/examples/eventproducers/.gitignore b/examples/eventproducers/.gitignore new file mode 100644 index 0000000..c60db30 --- /dev/null +++ b/examples/eventproducers/.gitignore @@ -0,0 +1 @@ +hostlist.json \ No newline at end of file diff --git a/examples/eventproducers/hoststatistics.coffee b/examples/eventproducers/hoststatistics.coffee new file mode 100644 index 0000000..e8c2443 --- /dev/null +++ b/examples/eventproducers/hoststatistics.coffee @@ -0,0 +1,67 @@ +fs = require 'fs' +# libnmap = require 'node-libnmap' +ping = require 'net-ping' +request = require 'request' + +try + arrHosts = JSON.parse fs.readFileSync 'hostlist.json', 'utf8' +catch err + console.error "Error reading host list file" + process.exit() + +remoteUrl = "http://ec2-54-226-188-9.compute-1.amazonaws.com:8126" + +# console.log arrHosts +# libnmap.nmap 'scan', +# range: arrHosts, +# callback: ( err, report ) -> +# if err +# console.log err +# else +# report.forEach ( item ) -> +# console.log item[ 0 ] + +session = ping.createSession() +everyMins = 10 +oHosts = {} +oPings = {} +fPollHosts = () -> + semaphore = arrHosts.length + pingTime = (new Date()).toISOString() + oPings[ pingTime ] = ips: [] + for host in arrHosts + session.pingHost host, ( err, target, sent, rcvd ) -> + if not err + if not oHosts[ target ] + oHosts[ target ] = {} + oHosts[ target ][ pingTime ] = (new Date( rcvd - sent )).getTime() + oPings[ pingTime ].ips.push target + + if --semaphore is 0 + console.log 'All ping requests returned, pushing event into the system' + oPings[ pingTime ].sum = oPings[ pingTime ].ips.length + fPushEvent + currentlyon: oPings[ pingTime ].ips.length + pingtimes: oPings + hosts: oHosts + + console.log "Pinging again in #{ everyMins } minutes" + setTimeout fPollHosts, everyMins * 60 * 1000 + +fPollHosts() + + +options = + method: 'POST' + json: true + jar: true + +fPushEvent = ( evt ) -> + options.url = remoteUrl + '/webhooks/uptimestatistics' + options.body = JSON.stringify evt + request options, ( err, resp, body ) -> + if err or resp.statusCode isnt 200 + console.log 'Error in pushing event!' + else + console.log 'Successfully posted an event' + diff --git a/webpages/handlers/remote-scripts/forge_module.html b/webpages/handlers/remote-scripts/forge_module.html index 8b336da..7311999 100644 --- a/webpages/handlers/remote-scripts/forge_module.html +++ b/webpages/handlers/remote-scripts/forge_module.html @@ -25,7 +25,7 @@ exports.newMail = () -> if resp.statusCode is 200 if body.Emails.length > 0 log "#{ body.Emails.length } mail events pushed into the system" - exports.pushEvent mail for mail in body.Emails + pushEvent mail for mail in body.Emails ### This will emit events of the form: diff --git a/webpages/public/chart.html b/webpages/public/chart.html new file mode 100644 index 0000000..3459186 --- /dev/null +++ b/webpages/public/chart.html @@ -0,0 +1,45 @@ + + + + + + + + + + + + {{{remote_scripts}}} + + + + {{{menubar}}} +
+
+

+
+ {{{content}}} +
+ + \ No newline at end of file diff --git a/webpages/public/data/histochart.json b/webpages/public/data/histochart.json new file mode 100644 index 0000000..943b68a --- /dev/null +++ b/webpages/public/data/histochart.json @@ -0,0 +1,157 @@ +{ + "currentlyon": 37, + "pingtimes": { + "2014-04-23T10:25:46.369Z": [ + "131.152.85.64", + "131.152.85.66", + "131.152.85.67", + "131.152.85.68", + "131.152.85.69", + "131.152.85.73", + "131.152.85.72", + "131.152.85.80", + "131.152.85.82", + "131.152.85.81", + "131.152.85.83", + "131.152.85.85", + "131.152.85.84", + "131.152.85.93", + "131.152.85.95", + "131.152.85.70", + "131.152.85.96", + "131.152.85.94", + "131.152.85.97", + "131.152.85.106", + "131.152.85.109", + "131.152.85.108", + "131.152.85.194", + "131.152.85.79", + "131.152.85.171", + "131.152.85.144", + "131.152.85.114", + "131.152.85.74", + "131.152.85.115", + "131.152.85.103", + "131.152.85.199", + "131.152.85.254", + "131.152.85.225", + "131.152.85.227", + "131.152.85.226", + "131.152.85.120", + "131.152.85.228" + ] + }, + "hosts": { + "131.152.85.64": { + "2014-04-23T10:25:46.369Z": 1 + }, + "131.152.85.66": { + "2014-04-23T10:25:46.369Z": 1 + }, + "131.152.85.67": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.68": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.69": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.73": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.72": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.80": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.82": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.81": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.83": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.85": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.84": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.93": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.95": { + "2014-04-23T10:25:46.369Z": 1 + }, + "131.152.85.70": { + "2014-04-23T10:25:46.369Z": 1 + }, + "131.152.85.96": { + "2014-04-23T10:25:46.369Z": 1 + }, + "131.152.85.94": { + "2014-04-23T10:25:46.369Z": 1 + }, + "131.152.85.97": { + "2014-04-23T10:25:46.369Z": 1 + }, + "131.152.85.106": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.109": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.108": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.194": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.79": { + "2014-04-23T10:25:46.369Z": 1 + }, + "131.152.85.171": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.144": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.114": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.74": { + "2014-04-23T10:25:46.369Z": 1 + }, + "131.152.85.115": { + "2014-04-23T10:25:46.369Z": 0 + }, + "131.152.85.103": { + "2014-04-23T10:25:46.369Z": 1 + }, + "131.152.85.199": { + "2014-04-23T10:25:46.369Z": 1 + }, + "131.152.85.254": { + "2014-04-23T10:25:46.369Z": 2 + }, + "131.152.85.225": { + "2014-04-23T10:25:46.369Z": 3 + }, + "131.152.85.227": { + "2014-04-23T10:25:46.369Z": 3 + }, + "131.152.85.226": { + "2014-04-23T10:25:46.369Z": 4 + }, + "131.152.85.120": { + "2014-04-23T10:25:46.369Z": 5 + }, + "131.152.85.228": { + "2014-04-23T10:25:46.369Z": 6 + } + } +} \ No newline at end of file