ติดตั้ง webmin บน Raspberry Pi

Download ตัวโปรแกรมติดตั้ง

wget http://prdownloads.sourceforge.net/webadmin/webmin_1.831_all.deb

ติดตั้ง library และโปรแกรมที่เกี่ยวข้อง

sudo apt-get install  libnet-ssleay-perl libauthen-pam-perl  libio-pty-perl  apt-show-versions  libapt-pkg-perl

หรือ sudo apt-get install perl libnet-ssleay-perl openssl libauthen-pam-perl libpam-runtime libio-pty-perl apt-show-versions python

ติดตั้ง webmin

sudo dpkg --install webmin_1.831_all.deb

Login เข้า webmin ด้วยคำสั่ง https://ชื่อเครื่องหรือไอพี:10000

ใส่ user: pi และรหัสผ่าน

 

 

การใช้คำสั่ง shell_exec ใน php

การใช้คำสั่ง shell_exec ใน php เช่น

$output = shell_exec('sudo /home/seal/bin/reload_iperf.sh');

การใช้คำสั่ง shell_exec ใน php ที่ทำงานบน web server นั้น จำเป็นต้องมีการตั้งค่าสิทธิอนุญาตการทำงานก่อน เพื่อให้คำสั่งดังกล่าวนั้นสามารถทำงานได้ การกำหนดสิทธินั้นทำได้ด้วยการระบุ ในไฟล์ /etc/sudoers ซึ่งสามารถแก้ไขได้ด้วยคำสั่ง sudo visudo

แล้วเพิ่ม โดย www-data คือ user ที่ใช้ run โปรแกรม web

www-data ALL=NOPASSWD: /home/seal/bin/reload_iperf.sh

เข้าไปในไฟล์ดังกล่าว

รายละเอียดเพิ่มเติมอ่านได้จาก http://unix.stackexchange.com/questions/115054/php-shell-exec-permission-on-linux-ubuntu

Audio Streaming Raspberry Pi

How to stream audio (line-in) to icecast — Raspberry Pi 3

Hardware lists:

  • USB Sound Card (Sound BLASTER SBX)
  • Raspberry Pi 3

list usb sound card

pi@raspberrypi:~ $ aplay -L | grep CARD

sysdefault:CARD=ALSA
dmix:CARD=ALSA,DEV=0
dmix:CARD=ALSA,DEV=1
dsnoop:CARD=ALSA,DEV=0
dsnoop:CARD=ALSA,DEV=1
hw:CARD=ALSA,DEV=0
hw:CARD=ALSA,DEV=1
plughw:CARD=ALSA,DEV=0
plughw:CARD=ALSA,DEV=1
sysdefault:CARD=Pro
front:CARD=Pro,DEV=0
surround21:CARD=Pro,DEV=0
surround40:CARD=Pro,DEV=0

capture audio from line-in :

arecord –device=sysdefault:CARD=Pro  –format S16_LE –rate 44100 -c 2

test sound :

aplay -D sysdefault:CARD=Pro

mix command arecord (send to stdin/stdout) and aplay

arecord –device=sysdefault:CARD=Pro  –format S16_LE –rate 44100 -c 2 | aplay -D sysdefault:CARD=Pro

 

Stream audio to icecast

we adopt the solution from https://one-button.org/node/48

convert audio to mp3 : lame -r -s 44.1 -m s -b 128 –cbr – –

stream to icecast : ezstream -c /etc/ezstream.xml

ezstream configuration file :

ezstream.xml

<ezstream>
    <url>http://localhost:8002/stream</url&gt;
    <sourcepassword>hackme</sourcepassword>
    <format>MP3</format>
    <filename>stdin</filename>
    <stream_once>1</stream_once> <!– must do for stdin –>
<!– the rest are optional –>
    <svrinfoname>Raspberry Pi Station</svrinfoname>
    <svrinfourl>http://radio.ogonan.com</svrinfourl&gt;
    <svrinfogenre>geek</svrinfogenre>
    <svrinfodescription>Stream Audio from YouTube</svrinfodescription>
    <!– the following taken from mplayer. not sure if it’s right –>
    <svrinfobitrate>128</svrinfobitrate>
    <svrinfochannels>2</svrinfochannels>
    <svrinfosamplerate>44100</svrinfosamplerate>
    <svrinfopublic>1</svrinfopublic>
</ezstream>

combine command :

arecord –device=sysdefault:CARD=Pro  –format S16_LE –rate 44100 -c 2 | lame -r -s 44.1 -m s -b 128 –cbr – – | ezstream -c /etc/ezstream.xml

Audio monitoring :

mplayer -ao alsa:device=hw=1.0 http://localhost:8002/stream

Notes :

Generate a Playlist

$ cd /path/to/music/dir
$ find -type f -iname \*.mp3 > playlist.txt

$ mplayer -shuffle -playlist playlist.txt

;mplayer -ao alsa:device=hw=1.0 -shuffle -playlist playlist.txt

Control and Monitoring by supervisor

create shell script : capture.sh

#!/bin/bash
arecord –device=sysdefault:CARD=Pro  –format S16_LE –rate 44100 -c 2 | lame -r -s 44.1 -m s -b 128 –cbr – – | ezstream -c /etc/ezstream.xml

create configuration file : /etc/supervisor/conf.d/capturehooks.conf

[program:capturehook]
command=/home/pi/Music/capture.sh
directory=/home/pi/Music
autostart=true
autorestart=true
startretries=3
stderr_logfile=/home/pi/Music/log/capturehook.err.log
stdout_logfile=/home/pi/Music/log/capturehook.out.log
user=pi

see https://www.digitalocean.com/community/tutorials/how-to-install-and-manage-supervisor-on-ubuntu-and-debian-vps

Record audio file every 1 minute

create shell script  local_record.sh

#!/bin/bash
adate=`date +”%Y%m%d_%H%M%S”`
FILE=”/home/pi/Music/files/radio_$adate.mp3″
arecord –device=sysdefault:CARD=Pro  –format S16_LE –rate 44100 -c 2 | lame -r -s 44.1 -m s -b 128 –cbr – “$FILE” &
sleep 61
kill %1

add to crontab :

* * * * * /home/pi/Music/local_record.sh >/dev/null 2>&1

 backup file to cloud :

rsync -avz -e “ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null” –progress /home/pi/Music/files/radio_20170329*.mp3 CATWEBCASTING @192.168.8.98:/Volumes/storagebkk01/media-cat/files/

Ref. https://www.digitalocean.com/community/tutorials/how-to-copy-files-with-rsync-over-ssh

Uninstalling McAfee Enterprise in Windows

from https://it.uoregon.edu/node/4094

It’s work but in my computer FrmInst.exe is in C:\Program Files\McAfee\Agent\x86 directory.

You should run cmd.exe in Administrator Mode.

use command : cd C:\Program Files\McAfee\Agent\x86

run : FrmInst.exe /remove=agent

after finished you should follow the instruction in https://it.uoregon.edu/node/4094

uninstall mcafee agent

Passwordless ด้วย auth0

ไปสมัครลองใช้ได้ที่

https://auth0.com/

จากนั้น สร้าง app ขึ้นมา ส่วน code แล้วแต่ความถนัด สามารถเลือกได้เกือบที่มีอยู่ในโลกนี้ ตัวอย่างนี้ใช้เขียนด้วย php ซึ่งสามารถดูตัวอย่างได้ผ่าน console หลังจากสร้าง app กรณีใช้ php ต้องลง library เพิ่มด้วยคำสั่ง

composer require auth0/auth0-php:"~4.0"

คำสั่ง composer ไปเอาที่นี่ https://getcomposer.org/doc/00-intro.md

สร้างหน้า Login

login.html

<html>
<body>

https://cdn.auth0.com/js/lock-passwordless-2.2.min.js

  var lock = new Auth0LockPasswordless('Client ID', 'kaebmoo.auth0.com
');
    lock.emailcode({
      callbackURL: 'http://auth.ogonan.com/callback.php',
      authParams: {
        scope: 'openid email'  // Learn about scopes: https://auth0.com/docs/scopes
      }
    });


</html>

Client ID = Client ID ของ App ที่สร้างขึ้นใน auth0 ส่วน

kaebmoo.auth0.com

kaebmoo ก็เป็น user ที่สร้างขึ้นใน auth0

กรณีนี้เป็นการใช้ passwordless แบบส่ง email ผ่าน mail server (SMTP) ของ SendGrid ซึ่งต้องไปเอา API Key มาใส่ไว้ใน Config (ผ่าน web console) ของ auth0 ด้วย ในกรณีที่ใช้ smtp อื่น ก็ขึ้นอยู่กับ smtp แต่ละเจ้า (ลองของ google app gmail แล้ว แต่ส่งไม่ได้ ไม่แน่ใจว่าติดปัญหาอะไร error ฟ้องมาว่า Invalid …) ซึ่งทั้งการส่งผ่าน sms และ email ทาง auth0 ไม่มีการให้บริการตรงนี้ให้ ไม่เหมือน Account Kit ของ Facebook ที่มีบริการส่งทั้ง SMS และ email ให้

สำหรับการส่ง sms ลองใช้ของ Twilio ก็สามารถใช้งานได้ แต่จะต้องมีการระบุหมายเลขผู้ใช้งานที่ Twilio ด้วยจึงจะสามารถใช้งานได้ (แบบทดลองใช้) สิ่งที่ต้องใช้จาก Twilio ได้แก่

  • Account SID
  • Auth Token

เพื่อเอามาระบุให้กับ auth0 สามารถส่ง SMS มายัง มือถือ ตอนที่ทำงาน Login สรุปก็คือ auth0 ไม่มี SMS Gateway, Mail Gateway ให้ auth0 ทำหน้าที่ Authen อย่างเดียว การส่ง SMS, email ต้องไปอาศัย gateway ที่อื่นส่ง

สร้าง Callback เพื่อทำการรับค่าจาก auth0 ก็คือเมื่อมีการ Login ใส่ Password หรือ Pin Code แล้ว auth0 จะมีการเรียกกลับมายัง server ที่ร้องขอการ authen เราจำเป็นต้องระบุ url หรือ code ที่เราจะต้องเขียนขึ้นเพื่อรับค่า code (key, token) ซึ่งจะนำเอาไปใช้งาน (ถ้า login สำเร็จ)

callback.php

<?php

// code ตัวอย่างใน dashboard ไม่มีบรรทัดนี้ ทำเอาปวดหัว ให้เพิ่มเข้าไปด้วย 
// แต่ตัวอย่างใน github เหมือนจะมี ถ้าไม่ใส่บรรทัด ถัดไปจะ error 
// /vendor จะได้มาตอนที่ใช้ composer ลง library ที่เกี่ยวข้องเพิ่ม 
require __DIR__ . '/vendor/autoload.php';

use Auth0\SDK\Auth0;

$auth0 = new Auth0(array(
    'domain'        => 'kaebmoo.auth0.com',
    'client_id'     => 'Client ID',
    'client_secret' => 'Client Secret',
    'redirect_uri'  => 'http://auth.ogonan.com/callback.php'
));

        $userInfo = $auth0->getUser();
        if (!$userInfo) {
    // We have no user info
    // redirect to Login
                echo "Login";
        } else {
    // User is authenticated
    // Say hello to $userInfo['name']
    // print logout button
                echo "Hello " . $userInfo['name'];
        }

?>

<html>
  <body class="home">
    
</body> </html>

Client ID, Client Secret เอามาจากค่าที่ได้จากการสร้าง App ใน auth0

ใน Callback นี้ จะมีการเรียก user information ขึ้นมาแสดง ถ้า Login สำเร็จ พร้อม พิมพ์ Hello ทักทาย ใน callback ก็เป็นหน้าที่ของผู้พัฒนา app จะเขียนเพิ่มเติมให้ไปทำงานในส่วนต่าง ๆ ที่เกี่ยวข้องต่อไป

อยากลอง? เชิญ  http://auth.ogonan.com/login.html

 

 

Passwordless ด้วย Account Kit by Facebook

สิ่งที่ท่านต้องมีในเบื้องต้น

  1. Facebook Account https://www.facebook.com
  2. Developer Account https://developers.facebook.com/async/onboarding/dialog/
  3. Facebook App ID https://developers.facebook.com/quickstarts/?platform=web

เมื่อสร้าง App แล้ว ให้เพิ่ม Products เข้าไปใน App ที่สร้างขึ้น โดยเลือก Account Kit

สิ่งที่ต้องใช้ใน example code

  • App ID
  • Account Kit app secret

รหัสพวกนี้เปิดดูได้ใน Dashboard ของ App ที่สร้างขึ้น

ระบุ Server URLs ใน Web Login setttings เป็น URL และ port ที่ code เราทำงานอยู่บน server ที่จะใช้งาน Account Kit เช่น code ทำงานบน server http://auth.ogonan.com ก็ใช้ชื่อนี้ลงดังกล่าวลงไป

clone source code จาก https://github.com/auth0-blog/blog-passwordless-authentication

sudo git clone https://github.com/auth0-blog/blog-passwordless-authentication

  1. ใน account-kit-passwordless
  2. Run npm install
  3. แก้ไข file server.js แทนค่า YOUR_FACEBOOK_APP_ID and YOUR_ACCOUNT_KIT_SECRET ด้วยค่า App ID และ ค่า Account Kit app secret
  4. แก้ไข file login.html ที่อยู่ใน /dist directory
  5. แทนค่า YOUR_FACEBOOK_APP_ID ด้วย App ID
  6. Run app ด้วยคำสั่ง node server
  7. เปิด browser ไปยัง url ของ server ผ่าน port 3000 เช่น http://auth.ogonan.com:3000 หรือ localhost:3000

package.json

{
  "name": "FacebookAccountKitPasswordless",
  "version": "0.0.1",
  "dependencies": {
    "body-parser": "^1.15.0",
    "express": "3.x",
    "guid": "0.0.12",
    "mustache": "^2.2.1",
    "querystring": "^0.2.0",
    "request": "^2.69.0"
  }
}

server.js

const fs = require('fs');
const Guid = require('guid');
const express = require('express');
const bodyParser = require("body-parser");
const Mustache  = require('mustache');
const Request  = require('request');
const Querystring  = require('querystring');
const app = express();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
  
var csrf_guid = Guid.raw();
const api_version = "v1.0";
const app_id = "YOUR_FACEBOOK_APP_ID";
const app_secret = 'YOUR_ACCOUNT_KIT_SECRET';
const me_endpoint_base_url = 'https://graph.accountkit.com/v1.0/me';
const token_exchange_base_url = 'https://graph.accountkit.com/v1.0/access_token'; 

function loadLogin() {
  return fs.readFileSync('dist/login.html').toString();
}

app.get('/', function(request, response){
  var view = {
    appId: app_id,
    csrf: csrf_guid,
    version: api_version,
  };

  var html = Mustache.to_html(loadLogin(), view);
  response.send(html);
});

function loadLoginSuccess() {
  return fs.readFileSync('dist/login_success.html').toString();
}

app.post('/sendcode', function(request, response){
  // CSRF check
  if (request.body.csrf_nonce === csrf_guid) {
    var app_access_token = ['AA', app_id, app_secret].join('|');
    var params = {
      grant_type: 'authorization_code',
      code: request.body.code,
      access_token: app_access_token
      //appsecret_proof: app_secret
    };
  
    // exchange tokens
    var token_exchange_url = token_exchange_base_url + '?' + Querystring.stringify(params);
    Request.get({url: token_exchange_url, json: true}, function(err, resp, respBody) {
      console.log(respBody);
      var view = {
        user_access_token: respBody.access_token,
        expires_at: respBody.expires_at,
        user_id: respBody.id,	
      };
      // get account details at /me endpoint
      var me_endpoint_url = me_endpoint_base_url + '?access_token=' + respBody.access_token;
      Request.get({url: me_endpoint_url, json:true }, function(err, resp, respBody) {
        // send login_success.html
        console.log(respBody);
        if (respBody.phone) {
          view.method = "SMS"
          view.identity = respBody.phone.number;
        } else if (respBody.email) {
          view.method = "Email"
          view.identity = respBody.email.address;
        }
        var html = Mustache.to_html(loadLoginSuccess(), view);
        response.send(html);
      });
    });
  } 
  else {
    // login failed
    response.writeHead(200, {'Content-Type': 'text/html'});
    response.end("Something went wrong. :( ");
  }
});

app.listen(3000);

ใน /dist มีอีกสองไฟล์ login.html login_success.html เอามาด้วย

https://github.com/auth0-blog/blog-passwordless-authentication/blob/master/account-kit-passwordless/dist/login.html

ตอนจะใช้งานก็ Run ด้วยคำสั่ง node server ซึ่ง server.js กำหนดให้ทำงานที่ port 3000 ถ้าจะเปลี่ยนเป็น port อื่น เช่น 80, 8080 ก็เปลี่ยนที่ บรรทัด app.listen(3000); เปลี่ยนจาก 3000 เป็น 80

ลองดู http://auth.ogonan.com:3000/

Raspberry Pi with 3G

How to use Raspberry pi 3 model B connect to internet via usb 3G or 4G.

Equipments :

Software Lists:

  • Sakis3g is a script which creates an Internet connection using 3G modems.
  • UMTSkeeper : keep your UMTS/GPRS/GSM connection alive automatically. now include the Sakis3G script with the UMTSkeeper download.

First check that you have ppp installed
sudo apt-get install ppp

Now download the Sakis3g package
sudo wget “http://www.sakis3g.com/downloads/sakis3g.tar.gz&#8221; -O sakis3g.tar.gz

Then unzip the file
sudo tar -xzvf sakis3g.tar.gz

Make the file executable
sudo chmod 755 sakis3g

And finally launch it
./sakis3g –interactive

Install UMTSkeeper read here http://mintakaconciencia.net/squares/umtskeeper/

cd ~
pwd
mkdir umtskeeper
cd umtskeeper
wget “http://mintakaconciencia.net/squares/umtskeeper/src/umtskeeper.tar.gz&#8221;
md5sum umtskeeper.tar.gz
tar -xzvf umtskeeper.tar.gz
chmod 755 sakis3g umtskeeper

plug usb modem into raspberry pi usb port.

use command lsusb to check.

pi@raspberrypi:~ $ sudo lsusb
Bus 001 Device 011: ID 12d1:1506 Huawei Technologies Co., Ltd. E398 LTE/UMTS/GSM Modem/Networkcard
Bus 001 Device 012: ID 05ac:0304 Apple, Inc. Optical USB Mouse [Mitsumi]
Bus 001 Device 009: ID 0461:0010 Primax Electronics, Ltd HP Keyboard
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
pi@raspberrypi:~ $

write down ID xxxx:xxxx in example is 12d1:1506

we will use this ID in command line argument.

run

/home/pi/umtskeeper/umtskeeper –sakisoperators “USBINTERFACE=’0′ OTHER=’USBMODEM’ USBMODEM=’12d1:1506‘ SIM_PIN=’0000′ APN=’CUSTOM_APN’ CUSTOM_APN=’internet’ APN_USER=’0′ APN_PASS=’0′” –sakisswitches “–sudo –console” –devicename ‘Huawei’ –log –silent –monthstart 8 –nat ‘no’ –httpserver &>> /home/pi/umtskeeper/error.log &

if you want start UMTSkeeper automatically after boot. Put a command above into /etc/rc.local ( /etc/rc.local has to be edited by the root user. ex. sudo vi /etc/rc.local).

  • the next setting is config vpn between pi and server. The setup instruction is in digitalocean tutorial.

How to share internet and wifi access point on 3G/4G Aircard with Raspberry pi 3 (pocket wifi)

Read instructions here https://frillip.com/using-your-raspberry-pi-3-as-a-wifi-access-point-with-hostapd/ but replace iptables options with this commands (because we connected to internet via ppp0 not eth0) :

sudo iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE  
sudo iptables -A FORWARD -i ppp0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT  
sudo iptables -A FORWARD -i wlan0 -o ppp0 -j ACCEPT  

 

Speed test by nuttcp

wait and see. 😉 will be soon.

On server side:

Software lists:

Working step

  1. Make Network Connection
  2. Make VPN Connection
  3. Scheduling Test by crontab
  4. Testing (shell script)
  5. Convert to JSON (text parsing)
  6. POST to web application by curl
  7. Insert to Database (php + mysql)

Display

  1. Read from Database
  2. Convert to Array (JSON)
  3. Display Graph by Google Chart API

Future work

Convert data to RRD by RRDTool