ラベル GAE の投稿を表示しています。 すべての投稿を表示
ラベル GAE の投稿を表示しています。 すべての投稿を表示

2013年3月3日日曜日

GAEでpython-on-a-chipオンラインコンパイラの試作


python-on-a-chip(pymite)でpythonコードを変更するたびに mbed の C++コンパイラを通すのは面倒なので、オンラインで直接実行ファイルを作れるか試してみました。

Google App Engine(GAE) で作ったWEBサイトでpythonコードを入力。
compileコンパイルボタンを押すと、pmImgCreator.py でバイトコードに変換、実行ファイルのバイトコードを入れ換えて、パソコンにダウンロードさせる。
mbedにドラッグアンドドロップで実行します。

厳密にテストしてはないのですが、python2.5 の pmImgCreator.py で作るバイトコードは動くようです。
そのために GAE では 2.7 が使えるのに、あえて python2.5 で動かしています。
jinjia2 はGAEローカル開発環境では動くが、オンライン環境では 2.7 が必要で、旧テンプレートエンジンを使用しなければならない。
簡単にWEBサイトを作るために、jQuery Mobile を使用しているのだが、ファイルのダウンロードはうまくいかない。
フォームでは ajax をディセーブルにする必要があります。

GAEでの試作例サイト:
http://pymbed.appspot.com/
GAEでの実行コード:
https://bitbucket.org/va009039/pymbed
python-on-a-chip実行ファイル作成のコード:
http://mbed.org/users/va009039/code/pymite/
mbedコンパイラへのインポートを助けるためのバッチファル make.bat:
http://mbed.org/users/va009039/code/pymite/wiki/makebat
オフラインコンパイルのためのバッチファイル compile.bat:
http://mbed.org/users/va009039/code/pymite/wiki/compilebat

(2013/3/3)
---

2013年1月23日水曜日

cosmのトリガーでメールを送る


cosmのトリガーHTTP POSTでGAEを叩いてメールを送っていたが、
メールの送り先をGAEの管理者に変更してみた。
管理者メールはGmailで登録しているので、フィルターで携帯電話に転送している。

センサーmbed → cosm → GAE → gmail → 携帯電話

15分間データの更新が無いとfrozenのトリガーがあるのでmbedが無反応になったのもわかります。


# cosmtrigger.py 2013/1/23
#coding: utf-8
import webapp2
from google.appengine.api import app_identity
from google.appengine.api import mail

class TriggerHandler(webapp2.RequestHandler):
    def post(self, param):
        json_str = self.request.get('body')
        mail.send_mail_to_admins(
              sender = "cosmtrigger@" + app_identity.get_application_id() + ".appspotmail.com",
              subject = "cosm trigger %s" % param, body = json_str)

app = webapp2.WSGIApplication([
    (r'/cosmtrigger/(.*)', TriggerHandler),
    ], debug=True)


(2013/1/23)
---

2012年12月8日土曜日

PythonでARMv7Mの逆アセンブラをつくる

mbedのコンパイラがどんなコードを出力するのか知りたかったので、PythonでARMv7Mの逆アセンブラをつくってみました。

dasv7m

GAEでも動くようにしてみました。

disassembler

たとえばLEDチカチカを逆アセンブラすると次のようになります。
(printf("%p\n", main);はmain()のアドレスを知るために追加してあります)
#include "mbed.h"
DigitalOut myled(LED1);
int main() {
    printf("%p\n", main);
    while(1) {
        myled = 1;
        wait(0.2);
        myled = 0;
        wait(0.2);
    }
}


(2012/12/8)
---

2012年9月30日日曜日

台風17号の記録

消防署が設置しているNEIの気象観測システムからデータをGAEのcronで取得してcosmで表示。
GAEで動かしていたプログラムはこれ(kisyo.py)です。








(2012/9/30)
---

2012年9月9日日曜日

JPEGからDHTセグメントを削除するプログラム

Windows7でGoogle ChromeはJPEGファイルのDHTセグメントが無くても表示できるが、IEでは表示できない。
Google製のPicasaでも表示できない。もちろんペイントでも表示できない。



mbedでUVCカメラを扱うプログラムを作成していた時に、なぜかロジクールのカメラだけ表示出来ない事に気がついた。調べてみるとロジクールのカメラから送られて来るモーションJPEGはDHTセグメントは付いていない。

表示できるようにJPEGファイルを変換する(DHTを付加する)Webサービスを作ろうと考えて、
アップロードしたファイルを出力するだけのプログラムを作ったら、Chromeだけ表示できる事がわかった。

最近、WebcamServerが表示できないという苦情が来た。ロジクールのカメラの場合はChromeを使えばいいと考えて
DHTはあえて付加していなかった。Chromeを使うようにお願いしても表示できない、MacのChromeらしい。
WebcamServer側でDHTを付加するように修正したら表示できると報告されたので、WindowsとMacではChromeの
仕様は違うのかもしれない。

サイト:http://va009039-mbed.appspot.com/jpeg/DHTstrip/

ソースコード:jpeg_DHTstrip.py
---

2012年4月22日日曜日

PachubeクライアントをGAEでデバッグする

Pachubeクライアントをデバッグする時に、ヘッダーに入れたキーが正しいか,
POSTしたデータ形式が正しいかをGAEでPachubeのAPIを作って調べる。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# gae_PachubeClient_debug.py 2012.4.21
import logging
import os
import re
import time
import datetime
import StringIO
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

class pachubeHandler(webapp.RequestHandler):
    def post(self,feeds):
        logging.info(feeds)
        method = self.request.get('_method')
        logging.info(method)
        headers = self.request.headers
        apikey = headers.get('X-PachubeApiKey')
        logging.info(apikey)
        body = self.request.body
        logging.info(body)
        self.response.out.write(" ")

application = webapp.WSGIApplication([
    (r'/v2/feeds/(\d+)\.csv', pachubeHandler),
], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == '__main__':
    main()
---

2012年3月13日火曜日

GAE/Pythonでtar.gzを解凍する

美咲フォントのBDF形式を扱いたかったので、まずは、Pythonでtar.gz形式の書庫を解凍するプログラムを組んでみた。


# -*- coding: utf-8 -*-
# gae_untargz.py 2012.3.13
import logging
import os
import StringIO
import tarfile
from google.appengine.api import users
from google.appengine.api import memcache
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app

class untargz(webapp.RequestHandler):
    def get(self):
        user = users.get_current_user()
 prefix = user.user_id()
 logging.info(prefix)
        targz_file = memcache.get(prefix + 'targz_file')
        filename = memcache.get(prefix + 'filename')
 action = self.request.get('action')
 member = self.request.get('member')
 members = []
 if targz_file:
     fileobj = StringIO.StringIO(targz_file)
     tar = tarfile.open(fileobj = fileobj, mode = 'r:gz')
            if action=='view':
  f = tar.extractfile(member)
  self.response.headers["Content-Type"] = "text/plain"
                self.response.out.write(f.read())
                return
     for tarinfo in tar:
         members.append(tarinfo.name)
 template_values = {'filename': filename, 'members': members, 'action': action}
        path = os.path.join(os.path.dirname(__file__), "templates", "untargz.html")
        self.response.out.write(template.render(path, template_values))

    def post(self):
        user = users.get_current_user()
 prefix = user.user_id()
        targz_file = self.request.get('targz_file')
        if targz_file:
            filename = self.request.body_file.vars['targz_file'].filename
     memcache.set(prefix + 'targz_file', targz_file, 180)
     memcache.set(prefix + 'filename', filename, 180)
        self.redirect('/untargz?action=list')

application = webapp.WSGIApplication([
    ('/untargz.*', untargz),
], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == '__main__':
    main()

---

2011年9月25日日曜日

DS18B20とmbedでデジタル温度計を試作(2)


実際の環境で使えるように改良。
・温度センサーを3.5ミニプラグに収めてみた。
ブレッドボードに刺さっている3.5ミニジャックはスイッチサイエンスのオーディオジャック+ピッチ変換基板のセットです。
・GAE以外にもPachubeにデータを送信するようにした。
・PachubeのトリガーでGAEを叩いてメールを送信するようにした。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# gae_ds18b20.py 2011.9.25
import logging
import datetime
from django.utils import simplejson
from google.appengine.api import app_identity
from google.appengine.api import mail
from google.appengine.ext import webapp
from google.appengine.ext.webapp.mail_handlers import InboundMailHandler
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
import owner_cfg

class ds18b20(db.Model):
    realTemp = db.FloatProperty()
    created = db.DateTimeProperty(auto_now_add=True)
    @property
    def created_jst(self): # 日本時間(テンプレートエンジン用)
        return self.created + datetime.timedelta(hours=9)

class ApiHandler(webapp.RequestHandler):
    def get(self, realTemp):
        data = ds18b20()
        data.realTemp = float(realTemp);
        data.put()
        self.response.out.write("RealTemp: %s" % realTemp)

class EmailHandler(InboundMailHandler):
    def receive(self, mail_message):
        message = mail.EmailMessage()
        message.sender = "ds18b20@" + app_identity.get_application_id() + ".appspotmail.com"
        message.to = mail_message.sender
        message.subject = u"DS18B20"
        query = ds18b20.all()
        data = query.order("-created").get()
        message.body = u"RealTemp: %f" % data.realTemp
        message.send()

class TriggerHandler(webapp.RequestHandler):
    def post(self, param):
        json_str = self.request.get('body')
        logging.info(json_str)
        obj = simplejson.loads(json_str)
        logging.info(obj)
        message = mail.EmailMessage()
        message.sender = "ds18b20-trigger@" + app_identity.get_application_id() + ".appspotmail.com"
        message.to = owner_cfg.to
        message.bcc = owner_cfg.bcc
        message.subject = u"DS18B20 TRIGGER %s" % param
        message.body = json_str
        message.send()

application = webapp.WSGIApplication([
    ('/ds18b20/api/(.+)', ApiHandler),
    ('/ds18b20/trigger/(.*)', TriggerHandler),
    EmailHandler.mapping(),
], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == '__main__':
    main()

---

2011年9月18日日曜日

DS18B20とmbedでデジタル温度計を試作(1)


mbed1-Wire温度センサDS18B20を接続してデジタル温度計を試作してみた。(奥に見えている白いのはDHT22で今回の試作には関係ありません)

うっかりしていたが、寄生電力モード(parasitic mode)で動かすときにはプルアップ抵抗4.7KΩでは大きい、2.2KΩにしたら動いた。

mbedではOneWireCRCにHTTPClientを追加して温度データを一定間隔でGAEにアップロードしています。
ケータイからメールリクエストで温度データを読み取ります。
以下はGAE側で動かしているソフトウェアです。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# gae_ds18b20.py 2011.9.17
import datetime
from google.appengine.api import app_identity
from google.appengine.api import mail
from google.appengine.ext import webapp
from google.appengine.ext.webapp.mail_handlers import InboundMailHandler
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db

class ds18b20(db.Model):
    realTemp = db.FloatProperty()
    created = db.DateTimeProperty(auto_now_add=True)
    @property
    def created_jst(self): # 日本時間(テンプレートエンジン用)
        return self.created + datetime.timedelta(hours=9)

class ApiHandler(webapp.RequestHandler):
    def get(self, realTemp):
        data = ds18b20()
        data.realTemp = float(realTemp);
        data.put()
        self.response.out.write("RealTemp: %s" % realTemp)

class EmailHandler(InboundMailHandler):
    def receive(self, mail_message):
        message = mail.EmailMessage()
        message.sender = "ds18b20@" + app_identity.get_application_id() + ".appspotmail.com"
        message.to = mail_message.sender
        message.subject = u"DS18B20"
        query = ds18b20.all()
        data = query.order("-created").get()
        message.body = u"RealTemp: %f" % data.realTemp
        message.send()

application = webapp.WSGIApplication([
    ('/ds18b20/api/(.+)', ApiHandler),
    EmailHandler.mapping(),
], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == '__main__':
    main()


(2011/9/18)
---

2011年8月15日月曜日

プリモバイルでみまもりケータイからの位置情報付きメールを地図表示する

プリモバイルではインターネットに接続できない。
みまもりケータイから送られて来た位置情報付きメールのURLを開くことは出来ない。
プリモバイルのメールし放題でGAEに転送して、代わりに地図の画像を取得して返信してもらう。
地図の画像の取得にはYahoo!デベロッパーネットワークのスタティックマップAPI、住所取得にはリバースジオコーダAPIを使っています。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# mimamori_simplemap.py 2011.8.3
import logging
import os
import datetime
import re
import urllib
from django.utils import simplejson
from google.appengine.api import app_identity
from google.appengine.api import urlfetch
from google.appengine.api import mail
from google.appengine.ext import webapp
from google.appengine.ext.webapp.mail_handlers import InboundMailHandler
from google.appengine.ext.webapp.util import run_wsgi_app
import yahoo_dev

def getgeo(text):
    pat = r'N(?P\d+)\.(?P\d+)\.(?P\d+\.\d+)E(?P\d+)\.(?P\d+)\.(?P\d+\.\d+)'
    m = re.search(pat, text)
    if m:
        lat = float(m.group('d1')) + float(m.group('m1')) / 60 + float(m.group('s1')) / 3600
        lon = float(m.group('d2')) + float(m.group('m2')) / 60 + float(m.group('s2')) / 3600
        return (lat, lon)
    else:
        return None

def yahoo_static_map(geo):
    api_url = "http://map.olp.yahooapis.jp/OpenLocalPlatform/V1/static"
    params = {
        'appid': yahoo_dev.my_appid,
        'pin': str(geo[0]) + "," + str(geo[1]),
        'width': "480",
        'height': "480",
        'z': "19",
    }
    query = urllib.urlencode(params)
    result = urlfetch.fetch(api_url + '?' + query)
    if result.status_code == 200:
        return result.content
    else:
        return None

def yahoo_revgeo(geo):
    api_url = "http://reverse.search.olp.yahooapis.jp/OpenLocalPlatform/V1/reverseGeoCoder"
    params = {
        'appid': yahoo_dev.my_appid,
        'lat': str(geo[0]),
        'lon': str(geo[1]),
        'output': 'json',
    }
    query = urllib.urlencode(params)
    result = urlfetch.fetch(api_url + '?' + query)
    if result.status_code == 200:
        json_str = result.content
        obj = simplejson.loads(json_str)
        address = obj['Feature'][0]['Property']['Address']
        logging.info(u"位置情報:" + address)
        return address
    else:
        return u"位置情報は取得できませんでした."

class simplemap_email(InboundMailHandler):
    def receive(self, mail_message):
        path = self.request.path
        logging.info("path: " + path)
        logging.info("Received a message from: " + mail_message.sender)

        body_text = image_data = ""
        plaintext = mail_message.bodies(content_type='text/plain')
        for text in plaintext:
            txtmsg = text[1].decode()
            logging.info("Body is %s" % txtmsg)
            geo =getgeo(txtmsg)
            logging.info(geo)
            if geo:
                body_text = yahoo_revgeo(geo)
                image_data = yahoo_static_map(geo)
                break

        message = mail.EmailMessage()
        message.sender = "simplemap@" + app_identity.get_application_id() + ".appspotmail.com"
        message.to = mail_message.sender
        message.subject = u"位置情報 " + mail_message.subject
        message.body = u"現在地:\n" + body_text
        if image_data:
            message.attachments = [("map.png", image_data)]
        message.send()

application = webapp.WSGIApplication([
    simplemap_email.mapping(),
], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()

---

2011年3月8日火曜日

GAEで対応クライアントをZIPファイルで配布する

GAEで作ったサーバーからクライアントソフトウェアをダウンロードして展開して実行するだけにしたい。

サーバーでAPIのURLやアプリキー等を書いた設定ファイルと実行ファイルをZIPファイルに纏めてダウンロードさせます。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# download.py 2011.3.7
import os
import logging
import urlparse
import random
import zipfile
import StringIO
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import login_required
from google.appengine.ext.webapp.util import run_wsgi_app

class download(webapp.RequestHandler):
    @login_required
    def get(self, filename):
        output = StringIO.StringIO()
        zip = zipfile.ZipFile(output, 'a')
        user = users.get_current_user()
        o = urlparse.urlparse(self.request.url)
        api_url = "http://" + o.netloc + "/api"
        appkey = "%08x" % random.randint(0x10000000, 0xffffffff)
        template_values = {'appkey': appkey, 'user_id':user.user_id(), 'api_url': api_url}
        path = os.path.join(os.path.dirname(__file__), "client", "client.ini")
        zip.writestr("client.ini", template.render(path, template_values))
        path = os.path.join(os.path.dirname(__file__), "client", "client.py")
        zip.write(path, "client.py")
        zip.close()
        self.response.headers['Content-Type'] = "application/zip"
        self.response.headers['Content-Disposition'] = 'attachment; filename="%s"' % filename
        self.response.out.write(output.getvalue())

application = webapp.WSGIApplication([
    ('/download/(client.zip)', download),
], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == '__main__':
    main()

2011年2月5日土曜日

ネットワークカメラからのメールをGAEで受信する

ネットワークカメラTS-LCAMの「動きを検知するとメールを送信する」設定にすると膨大なメールが送られて来てしまうので、メールの宛先をGAE(Google App Engine)にして、間引いて画像を保存したり転送するのはどうだろう。

attachmentsにはファイル名とEncodedPayloadが格納されている。
画像ファイル(バイト文字列)にするにはデコードしなければならない。

下記のプログラム例ではメールでJPEG画像を添付して送ると、キャッシュに保存されて /email_view/ファイル名 で見ることが出来ます。

しかし、TS-LCAMはSMTPのポート設定が出来ないようでOP25BのISPではメールが送れないようだ。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# email_unpack2.py 2011.2.5
import logging
from google.appengine.api import memcache
from google.appengine.ext import webapp
from google.appengine.ext.webapp.mail_handlers import InboundMailHandler
from google.appengine.ext.webapp.util import login_required
from google.appengine.ext.webapp.util import run_wsgi_app

class email_view(webapp.RequestHandler):
    @login_required
    def get(self, filename):
        if filename:
            image_data = memcache.get('filename_' + filename)
            if image_data:
                self.response.headers['Content-Type'] = "image/jpeg"
                self.response.out.write(image_data)
                return
        self.error(404)

class email_unpack(InboundMailHandler):
    def receive(self, mail_message):
        path = self.request.path
        logging.info("path: " + path)
        logging.info("Received a message from: " + mail_message.sender)
        if hasattr(mail_message, 'attachments'):
            for filename, content in mail_message.attachments:
                image_data = content.decode()
                logging.info("filename: %s, size: %d" % (filename, len(image_data)))
                memcache.set('filename_' + filename, image_data, time=60)

application = webapp.WSGIApplication([
    ('/email_view/(.*)', email_view),
    email_unpack.mapping()
], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()