Basic Information

This page allows you to fork a new project from an existing project (twit-counter). The newly forked project will be listed in the IoT Projects page as a new entry. If you want to overwrite the existing project, please edit it instead.

* Photo URLs that end with any one of .jpg, .jpeg, .png or that are uploaded to the Gyazo web service in the PNG format (e.g.https://gyazo.com/hogehoge) are supported.

{ "dependencies": { "twitter": "latest" } }

* Node.js entry point main: index.js and dependencies to the npm module dependencies: { f3js: (略) } will be automatically added and thus do not need to be in this form.

Card preview
twit-counter
'16/9/7 1:47
Count tweets which includes specified word and visualize it using LED, LCD and buzzer.
arc@dmz

Private Project

Unchecking this will make the project public and be listed in the IoT Projects page. The checkbox is unchecked by default since we want you to share the projects! Additionally, you cannot check this unless you are logged in. Once you make the project public, it cannot be undone. (Any edits to the project except for forking will also be public.)

Source Code

Provide the source code of a microcontroller or tiny computer in JavaScript. Node.js-based computers are supported. Require f3js package and use its API to design the device enclosure.

var GroveSensor = require('jsupm_grove'); var touchSensor = require('jsupm_ttp223'); var button = new GroveSensor.GroveButton(2); var GCL = require("jsupm_grovecircularled"); var circle = new GCL.GroveCircularLED(6, 5); var joystick = require("jsupm_joystick12"); var js12 = joystick.Joystick12(1,0); var upmBuzzer = require("jsupm_buzzer"); var buzzer = new upmBuzzer.Buzzer(5); var LCD = require("jsupm_i2clcd"); var lcd = new LCD.Jhd1313m1(6, 0x3E, 0x62); var f3js = require('f3js') , c = f3js.createContainer() , x = 10 , y = 10 , width = 160 , height = 105 , thickness = 42 , jw = 7 /* かみ合わせ幅 [5, 10] */ , jh = 2 /* 板厚[mm] [1, 5] */; c.x = x; c.y = y; // 表の面を作る var p = c.jrc(0, 0, width, height, jw, jh); /* // 上記は次のコードと同じ //var p = c.drawJointRectangle(0, 0, width, height, jw, jh); // または次のコードと同じ var p = c.createPath(); p.moveTo(0, 0); p.jointTo(width, 0, jw, jh); p.jointTo(width, height, jw, jh); p.jointTo(0, height, jw, jh); p.jointTo(0, 0, jw, jh); p.close(); */ var q = c.createPath(); q.moveTo(403.62352507915125,239.0229776213962); q.curveTo(389.2264079775014,271.3862825528054,338.7830733529945,255.3361306268153,351.3939070091431,218.07684937008023); q.moveTo(351.3889120447166,218.17752245296873); q.curveTo(323.4092051220599,212.69883358085212,299.82959036908113,220.09635977785678,283.6394816644336,246.74191342514774); q.moveTo(288.83719104162054,209.101483931964); q.curveTo(278.33363986332967,215.90008422508987,275.27458160010144,235.61401525475398,284.1098472004286,246.4500468547182); q.moveTo(288.8488587621546,209.11156500230925); q.curveTo(283.76624433012034,208.76309927626835,281.04708142947015,209.44289000142442,277.3139537755869,212.84102596186165); q.moveTo(299.65946712943696,175.6901163246728); q.curveTo(282.3391748710491,182.45454500937407,277.2407444323354,192.31151052421478,277.35940875589426,212.81849947254304); q.moveTo(299.7384302274568,175.76907942269364); q.curveTo(295.3226866578599,173.41398156787648,291.92945436655464,173.07326853992942,283.7719656646127,176.13232680315764); q.moveTo(319.9049979038448,151.60132567015307); q.curveTo(302.1263152439647,148.94069779670764,287.51081465300564,157.09818649863226,283.95188657225754,176.01185484578883); q.moveTo(319.9049979038448,151.60132567015307); q.curveTo(310.9258796645881,138.26122622341342,289.65799184819383,132.71308157564818,276.7123210034004,131.32604541370688); q.moveTo(411.92836821220726,222.39624903717527); q.curveTo(417.7276641339751,159.0667686525096,359.93449071980865,97.11248675251916,276.8266809523136,131.41004614810413); q.moveTo(403.5837362621135,239.0229776213962); q.curveTo(409.8680566813256,240.07245459062992,416.5887329838601,243.0967589267559,420.9571725804998,246.45709707804883); q.moveTo(420.9714493072985,246.58285285843218); q.curveTo(418.67296227995075,237.821503930606,413.58810481634146,233.8420502634306,408.7243281120234,230.96800039268902); q.moveTo(425.99767980740495,233.01574447297983); q.curveTo(420.61985494398215,231.68789817395023,413.9874321653564,229.6981713403625,408.7243281120234,230.96800039268902); q.moveTo(425.967030384085,233.13729419854963); q.curveTo(422.6524159471262,227.87286976267868,415.5778316499292,224.11449685479454,411.9282426343674,222.34775988118957); /* var sp = c.drawCircle(355, 180, 30); sp.fill = true; sp.stroke = false; */ // 表面にいろいろ配置する c.add(circle, { x: 355 + 0, y: 180 + 0 }); c.add(lcd, { x: 50 + 0, y: 70 + 0 }).rotate(180); c.add(button, { x: 140 + 0, y: 80 + 0 }); c.add(js12, {x: 110, y: 70}).rotate(90); c.add(buzzer, {x:140, y: 31}); // 配線用の穴を開ける c.drawRectangle(70, 10, 10, 6); c.drawRectangle(135, 59, 10, 6); c.drawRectangle(135, 10, 10, 6); c.drawRectangle(105, 39, 10, 6); //c.drawText("Mode", 132, 90); // 側面と裏面を作る var ps = p.extrude(45); ps[0].x = width + 5; ps[0].y = jh; ps[1].x = width + 5; ps[1].y = (thickness + 5) * 2 + jh; ps[2].x = width + 5; ps[2].y = thickness + 5 + jh; ps[3].x = width + 5; ps[3].y = (thickness + 5) * 3 + jh; ps[4].x = 0; // 最後の要素が裏面 ps[4].y = height + 5; // 表の面の真下に配置する for (var i = 0; i < ps.length; i ++) { c.add(ps[i]); } // 側面の一つに電源用の穴を開ける ps[1].drawRectangle(jh + 5, thickness - jh - 5, height - jh*2 - 10, -10); // 以降はゲームのソースコード var twitter = require('twitter'); // Twitterの認証情報 var twitterConsumerKey = ''; // Twitter Consumer Key var twitterConsumerSecret = ''; // Twitter Consumer Secret var twitterAccessTokenKey = ''; // Twitter Access Token Key var twitterAccessTokenSecret = ''; // Twitter Access Token Secret var chars = ['a' ,'b' ,'c' ,'d' ,'e' ,'f' ,'g' ,'h' ,'i' ,'j' ,'k' ,'l' ,'m' ,'n' ,'o' ,'p' ,'q' ,'r' ,'s' ,'t' ,'u' ,'v' ,'w' ,'x' ,'y' ,'z' ,' ']; String.prototype.trim = function() { return String(this).replace(/^\s+|\s+$/g, ''); }; var repeat = function (c, len) { s = ''; for (i = 0; i < len; i++) { s += c; } return s; }; var decstr = function (w, c) { ww = ''; for (i = 0; i < w.length; i++) { if (i === c) { var code = chars.indexOf(w[i]); ww += chars[(chars.length + code - 1) % chars.length]; } else { ww += w[i]; } } return ww; }; var incstr = function (w, c) { ww = ''; for (i = 0; i < w.length; i++) { if (i === c) { var code = chars.indexOf(w[i]); ww += chars[(code + 1) % chars.length]; } else { ww += w[i]; } } return ww; }; var normalize = function (p, m) { if (p > m) { return 1.0; } else if (p < 0) { return 0.0; } else { return p / m; } }; var CHARS_PER_LINE = 16; //var chords = []; //chords.push(upmBuzzer.DO); //chords.push(upmBuzzer.RE); //chords.push(upmBuzzer.MI); //chords.push(upmBuzzer.FA); //chords.push(upmBuzzer.SOL); //chords.push(upmBuzzer.LA); //chords.push(upmBuzzer.SI); //chords.push(upmBuzzer.DO); //chords.push(upmBuzzer.SI); //var chordIndex = 0; var level = 0; var count = 0; var word = 'http' + repeat(' ', CHARS_PER_LINE - 4); var t0 = Date.now(); buzzer.stopSound(); buzzer.setVolume(0.02); // editing or streaming var editing = false; // twitter streaming api tw = new twitter({ consumer_key: twitterConsumerKey, consumer_secret: twitterConsumerSecret, access_token_key: twitterAccessTokenKey, access_token_secret: twitterAccessTokenSecret }); tw.stream('statuses/sample', function (stream) { stream.on('data', function (data) { // console.log(data); if (data.text !== undefined) { if (!editing && data.text.toLowerCase().search(word.trim()) >= 0) { // console.log(data.text); level += 1; count += 1; circle.setLevel(level % 24); if (level % 24 === 0) { buzzer.playSound(upmBuzzer.SI, 20000); // buzzer.playSound(chords[chordIndex % chords.length], 100000); // chordIndex++; } else { buzzer.playSound(upmBuzzer.DO, 10000); } buzzer.stopSound(); } } }); }); // display handler var current_cursor = 0; var display = new i2c.LCD(0); var newpos = false; setInterval(function () { if (editing) { display.setColor(0, 60, 255); display.setCursor(0, 0); display.write('Enter word '); display.setCursor(1, 0); display.write(word); display.setCursor(1, current_cursor); if (newpos) { display.write('#'); } } else { var tps = count / (Date.now() - t0) * 1000; display.setColor(255 * normalize(tps, 20), 60, 255 * (1 - normalize(tps , 20))); display.setCursor(0, 0); display.write('word:' + word); display.setCursor(1, 0); display.write(tps.toFixed(2) + ' tweets/s '); } }, 100); // button handler var button = new groveSensor.GroveButton(2); var js0 = new joystick.Joystick12(1, 0); var initX01 = js0.getXInput(); var initY01 = js0.getYInput(); var prev_on = false; var epsilon = 0.1; setInterval(function () { var on = button.value(); if (on && !prev_on) { editing = !editing; t0 = Date.now(); count = 0; level = 0; newpos = true; circle.setLevel(level); } prev_on = on; }, 100); // joystick handler setInterval(function () { if (editing) { var x = js0.getXInput() - initX01; var y = js0.getYInput() - initY01; // console.log(x, y); if (x < -epsilon && current_cursor > 0) { current_cursor--; newpos = true; } else if (x > epsilon && current_cursor < CHARS_PER_LINE) { current_cursor++; newpos = true; } var spos = word.search(' '); if (spos < 0 || spos >= current_cursor) { if (y < -epsilon) { word = decstr(word, current_cursor); newpos = false; } else if (y > epsilon) { word = incstr(word, current_cursor); newpos = false; } } } }, 100); // SIGINT handler process.on('SIGINT', function () { buzzer.stopSound(); circle.setLevel(0); circle = null; GCL.cleanUp(); console.log('Exiting...'); process.exit(0); });
Customization

This content does not allow any customization.

Layout view options
Adding comments to variable declarations in the source code populate various GUI widgets in the "Customization" section depending on their types.

Design Alternatives

Modules

No modules are required for this project.

Layout
Program

Login first to use this feature.