'use strict';
var keyFilename = ""; // YOUR_KEY_FILE_NAME
var projectId = ""; // YOUR_PROJECT_ID;
var translateKey = ""; // YOUR_TRANSLATE_KEY;
var mraa = require("mraa");
var touch_sensor_value = 0, last_t_sensor_value;
var jsUpmI2cLcd = require('jsupm_i2clcd');
var lcd = new jsUpmI2cLcd.Jhd1313m1(6, 0x3E, 0x62);
var touchSensor = require('jsupm_ttp223');
var touch = new touchSensor.TTP223(0);
var working = false;
lcd.setColor(0, 0, 255);
lcd.setCursor(0, 0);
lcd.write('Initializing Goo');
lcd.setCursor(1, 0);
lcd.write('gle API... ');
var vision = require('gcloud')({
keyFilename: keyFilename,
projectId: projectId
}).vision();
var googleTranslate = require('google-translate')(translateKey);
lcd.setColor(0, 255, 0);
lcd.setCursor(0, 0);
lcd.write('Ready! ');
lcd.setCursor(1, 0);
lcd.write(' ');
var detect = function () {
vision.detectText('result.png', function (err, text) {
if (text && text[0]) {
var string = text[0].replace(/(?:\r\n|\r|\n)/g, ' ').replace(/[^0-9a-z ]/gi, '');
console.log(string);
googleTranslate.translate(string, 'en', function (err, translation) {
console.log(translation.translatedText);
lcd.setColor(255, 255, 255);
lcd.setCursor(0, 0);
lcd.write(' ');
lcd.setCursor(0, 0);
lcd.write(translation.translatedText.slice(0, 16));
lcd.setCursor(1, 0);
lcd.write(' ');
lcd.setCursor(1, 0);
lcd.write(translation.translatedText.slice(16, 31));
working = false;
});
} else {
lcd.setColor(255, 0, 0);
lcd.setCursor(0, 0);
lcd.write('Error... ');
lcd.setCursor(1, 0);
lcd.write(' ');
working = false;
}
});
};
setInterval(function () {
// https://github.com/intel-iot-devkit/upm/blob/master/examples/javascript/ttp223.js
touch_sensor_value = touch.isPressed();
if (touch_sensor_value === 1 && last_t_sensor_value === 0 && !working) {
lcd.setColor(0, 0, 255);
lcd.setCursor(0, 0);
lcd.write('Taking Picture..');
lcd.setCursor(1, 0);
lcd.write('. ');
working = true;
main();
}
last_t_sensor_value = touch_sensor_value;
}, 500);
var main = function () {
takePicture();
};
var takePicture = function () {
var v4l2camera = require("v4l2camera");
var cam = new v4l2camera.Camera("/dev/video0");
if (cam.configGet().formatName !== "YUYV") {
console.log("YUYV camera required");
process.exit(1);
}
cam.configSet({width: 352, height: 288});
cam.start();
times(6, cam.capture.bind(cam), function () {
var rgb = yuyv2rgb(cam.toYUYV(), cam.width, cam.height);
saveAsPng(rgb, cam.width, cam.height, "result.png");
cam.stop();
});
};
var ocr = function () {
lcd.setColor(0, 0, 255);
lcd.setCursor(0, 0);
lcd.write('Executing pictur');
lcd.setCursor(1, 0);
lcd.write('e... ');
setTimeout(detect, 3000);
};
var times = function (n, async, cont) {
return async(function rec(r) {return --n === 0 ? cont(r) : async(rec);});
};
var saveAsPng = function (rgb, width, height, filename) {
var fs = require("fs");
var pngjs = require("pngjs");
var png = new pngjs.PNG({
width: width, height: height, deflateLevel: 1, deflateStrategy: 1,
});
var size = width * height;
for (var i = 0; i < size; i++) {
png.data[i * 4 + 0] = rgb[i * 3 + 0];
png.data[i * 4 + 1] = rgb[i * 3 + 1];
png.data[i * 4 + 2] = rgb[i * 3 + 2];
png.data[i * 4 + 3] = 255;
}
png.pack().pipe(fs.createWriteStream(filename));
lcd.setColor(0, 255, 0);
lcd.setCursor(0, 0);
lcd.write('Picture successf');
lcd.setCursor(1, 0);
lcd.write('ully taken! ');
ocr();
};
var minmax = function (min, v, max) {
return (v < min) ? min : (max < v) ? max : v;
};
var yuv2r = function (y, u, v) {
return minmax(0, (y + 359 * v) >> 8, 255);
};
var yuv2g = function (y, u, v) {
return minmax(0, (y + 88 * v - 183 * u) >> 8, 255);
};
var yuv2b = function (y, u, v) {
return minmax(0, (y + 454 * u) >> 8, 255);
};
var yuyv2rgb = function (yuyv, width, height) {
var rgb = new Array(width * height * 3);
for (var i = 0; i < height; i++) {
for (var j = 0; j < width; j += 2) {
var index = i * width + j;
var y0 = yuyv[index * 2 + 0] << 8;
var u = yuyv[index * 2 + 1] - 128;
var y1 = yuyv[index * 2 + 2] << 8;
var v = yuyv[index * 2 + 3] - 128;
rgb[index * 3 + 0] = yuv2r(y0, u, v);
rgb[index * 3 + 1] = yuv2g(y0, u, v);
rgb[index * 3 + 2] = yuv2b(y0, u, v);
rgb[index * 3 + 3] = yuv2r(y1, u, v);
rgb[index * 3 + 4] = yuv2g(y1, u, v);
rgb[index * 3 + 5] = yuv2b(y1, u, v);
}
}
return rgb;
};
// ----------------------------------------------------------------
// グローバルな設定
var band_width = 25
, band_thickness = 2
, margin = 2;
// ----------------------------------------------------------------
// 腕に付けるlcd用ケース (http://f3js.org/projects/200 からコピー)
var iw = 90
, ih = 52
, id = 10 + band_thickness
, dw = 7 //ギザギザの幅
, dh = 2 // ギザギザの深さ
, w = iw + dh*2 + margin*2 // + dh*2 で板厚を考慮
, h = ih + dh*2 + margin*2
, d = id + dh*2 + margin*2
, f3js = require('f3js')
, c = f3js.createContainer()
, p = c.drawJointRectangle(0, 0, w, h, dw, dh);
// 板の左上から1cm余白あける
c.x = 10;
c.y = 10;
// 基板の脇に立つ4枚
var planes = p.extrude(d);
planes[0].x = w;
planes[0].y = 0;
planes[1].x = w;
planes[1].y = d * 2;
planes[2].x = w;
planes[2].y = d;
planes[3].x = w;
planes[3].y = d * 3;
for (var i = 0; i < planes.length - 1; i ++) c.add(planes[i]);
//信号ケーブルの穴(前)
var c2 = c.cc();
c2.x = planes[1].x ;
c2.y = planes[1].y;
c2.rc( dh + margin + 3, dh+margin, 10, 8);
//バンド用の穴
var c_band0 = c.cc();
c_band0.x = planes[0].x ;
c_band0.y = planes[0].y;
c_band0.rc(w / 10 + dh , dh + margin, band_width, band_thickness);
c_band0.rc( w * 9 / 10 - dh -band_width , dh + margin, band_width, band_thickness);
var c_band2 = c.cc();
c_band2.x = planes[2].x ;
c_band2.y = planes[2].y;
c_band2.rc(w / 10 + dh , dh + margin, band_width, band_thickness);
c_band2.rc( w * 9 / 10 - dh - band_width , dh + margin, band_width, band_thickness);
c.rc(dh +37 , 1.5*h -7.5/2 -dh, 17.5, 3);
c.rc(dh +37 ,1.5*h +7.5/2-dh, 17.5, 3);
// 基板の上にかぶさる1枚
var c3 = c.cc();
c3.y = h;
c3.add(planes[4]);
//touch
c2.rc( 25 + dh ,8 +dh + margin, 15, 2);
c2.drawCircle(20 + dh + margin,dh + margin+1.5, 1.6);
c2.drawCircle(40 + dh + margin,dh + margin+1.5, 1.6);
//部品
c.add(lcd, { x: 50, y: 30 });
//c.add(touch, { x: c.x + w + dh + margin, y: 30})
// ----------------------------------------------------------------
// main box (http://f3js.org/projects/199 からコピー)
f3js.addPage();
var iw = 122 // 幅[mm]
, ih = 72 // 高さ[mm]
, id = 40 + band_thickness// 奥行[mm]
, margin = 2
, dw = 7 //ギザギザの幅
, dh = 2 // ギザギザの深さ
, w = iw + dh*2 + margin*2 // + dh*2 で板厚を考慮
, h = ih + dh*2 + margin*2
, d = id + dh*2
, f3js = require('f3js')
, c = f3js.createContainer()
, p = c.drawJointRectangle(0, 0, w, h, dw, dh);
// 板の左上から1cm余白あける
c.x = 10;
c.y = 10;
// 基板を固定する穴6つ
c.drawCircle(105 + dh + margin, 12 + dh, 1.6);
c.drawCircle(105 + dh + margin, h - dh - 12, 1.6);
c.drawCircle(55 + dh + margin, dh + 17, 1.6);
c.drawCircle(55 + dh + margin, h - dh - 28, 1.6);
c.drawCircle(6 + dh + margin, dh + 6, 1.6);
c.drawCircle(6 + dh + margin, h - dh - 13, 1.6);
//circle.x = iw - 65.995 + dh;
//circle.y = 45.683 + dh;
//circle.r = 1.6;
// 基板の脇に立つ4枚
var planes = p.extrude(d);
planes[0].x = w;
planes[0].y = 0;
planes[1].x = w;
planes[1].y = d * 2;
planes[2].x = w;
planes[2].y = d;
planes[3].x = w;
planes[3].y = d * 3;
for (var i = 0; i < planes.length - 1; i ++) c.add(planes[i]);
// USBケーブルと電源ケーブルを通す穴
var c2 = c.cc(); //createContainer
c2.x = planes[1].x;
c2.y = planes[1].y;
c2.rc(3 + dh + margin, dh + margin + band_thickness, 65, 17);
//信号ケーブルの穴(前後)
var c2 = c.cc();
c2.x = planes[1].x ;
c2.y = planes[1].y;
c2.rc( h / 2.0 - 5.0 / 2, 25 + dh + margin + band_thickness, 10, 5);
var c3 = c.cc(); //createContainer
c3.x = planes[3].x ;
c3.y = planes[3].y;
c3.rc( h / 2.0 - 5.0 / 2, 25 + dh + margin + band_thickness, 10, 5);
//バンド用の穴
var c_band0 = c.cc();
c_band0.x = planes[0].x ;
c_band0.y = planes[0].y;
c_band0.rc(w / 10 + dh , dh + margin, band_width, band_thickness);
c_band0.rc( w * 9 / 10 - dh -band_width , dh + margin, band_width, band_thickness);
var c_band2 = c.cc();
c_band2.x = planes[2].x ;
c_band2.y = planes[2].y;
c_band2.rc(w / 10 + dh , dh + margin, band_width, band_thickness);
c_band2.rc( w * 9 / 10 - dh -band_width , dh + margin, band_width, band_thickness);
// 基板の上にかぶさる1枚
var c3 = c.cc();
c3.y = h;
c3.add(planes[4]);