pco2699’s blog

学んだコード・技術について、保存しておく場所

GrovePiの実装を実機テストなしでできてしまうGrovePiエミュレータの使い方

言いたいこと

Groveってはんだ付けなしでセンサがつくれて便利…!
GrovePiってGroveセンサをRasPiに繋げられて更に便利..! でも、GrovePiをつかったプログラムを組むとき、わざわざ実機テストするのはめんどくさい…!
と思っていたら、こんな便利なGrovePiエミュレータがありました。
(GrovePi自体はNodeやJavaでも動きますが、本エミュレータPythonでしか動かないようです…!)

github.com

使い方

基本 Macでの使用を前提しています

GrovePiエミュレータをgitからもってくる

$ git clone https://github.com/joemarshall/grovepi-emulator.git

GrovePiエミュレータを立ち上げる

$ cd grovepi-emulator
$ python grovepiemu.py

そうするっとアッラー素敵なGUIが立ち上がります
f:id:pco2699:20170806195013p:plain

GrovePi用のPythonスクリプトの実行

Pythonスクリプトを以下の「Load…」部から指定すると
GUIで指定したセンサの値が入力されている前提で、エミュレータが動いてくれます。
f:id:pco2699:20170806195124p:plain

動かすスクリプトは以下の通り、GrovePiのライブラリをimportした 前提で実装すれば、エミュレータがよしなにやってくれるみたいです

import grovepi
import time

if __name__ == '__main__':
    while True:
        input = grovepi.analogRead(0)
        print(input)
        time.sleep(1)

Pythonでインスタンスメソッドの中で、宣言した変数はインスタンスメソッド内限定の変数となる

言いたいこと

Pythonのクラスの作り方はわかりづらい。
クラス変数とインスタンス変数、普通の関数内変数がどのように扱われるかがわからない!
ということで、以下のようなテストコードを書いてみた。

基本的には、以下の理解でよいみたい

  • selfをつけるとインスタンス変数
  • classの直下で宣言された変数はクラス変数
  • 各メソッド内で宣言された変数は関数内変数

コード

 -*- coding: utf-8 -*-

class Hoge():
    hoge = "私はクラス変数としてのhoge" #これはクラス変数として扱われる

    def __init__(self):
        self.hoge = "私はインスタンス変数としてのほげ" # selfをつけるとインスタンス変数
        hoge = "私はinit関数内としてのほげ" # これはinit関数内限定の変数

    def test(self):
        hoge = "私はインスタンスメソッドの中のほげ"  # test内関数の変数
        print(hoge) # -> 私はインスタンスメソッドの中のほげ
        print(self.hoge) # -> 私はインスタンス変数としてのほげ

    @classmethod
    def test_cls_hoge(cls):
        print(cls.hoge) # -> 私はクラス変数としてのhoge

def main():
    hoge = Hoge()
    hoge.test()
    Hoge.test_cls_hoge()

if __name__ == '__main__':
    main()

Vue.jsで簡単なタイマーアプリ

つくりましたよ

Vue.js/Moment.jsで簡単なカウントダウン日付タイマーをつくりました

コード

js部

import moment from 'moment'
import Vue from 'vue'

let now_date = moment()

let date_format = 'YYYY:MM:DD HH:mm:ss'

let submission_date = moment('2017-09-22 23:59')
let presentaion_date = moment('2017-10-12 23:59')

const vm = new Vue({
  el: '#date',
  data: {
    now_date: now_date.format(date_format),
    submission_remain_days: now_date.diff(gga_submission_date, 'days'),
    presentaion_remain_days: now_date.diff(gga_presentaion_date, 'days')
  },
});

setInterval(()=>{
  vm.now_date = moment().format(date_format)
},1000)

html部

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello Vue</title>
  </head>
  <body>
    <div id="date">
      <div class="row">
        <span class="label">現在日付:</span> <span class="data">{{now_date}}</span>
      </div>
      <div class="row">
        <span class="label">提出締切: </span> <span class="data">{{gga_submission_remain_days * -1}} </span>
      </div>
      <div class="row">
        <span class="label">発表: </span> <span class="data">{{gga_presentaion_remain_days * -1}} </span>
      </div>
    </div>
    <script src="dist/bundle.js"></script>
  </body>
</html>

つまづきポイント

現在の日付を書き換えるのに、

let now_date = moment()

const vm = new Vue({
  el: '#date',
  data: {
    now_date: now_date.format(date_format), // ここでnow_dateをvmのdata部に設定
    submission_remain_days: now_date.diff(gga_submission_date, 'days'),
    presentaion_remain_days: now_date.diff(gga_presentaion_date, 'days')
  },
});

setInterval(()=>{
  now_date = moment().format(date_format) // 間違えてnow_date側のオブジェクトを取得しちゃっている...
},1000)

と、vueのdata部じゃなくて、設定するオブジェクト側を書き換えてたんだけど
もちろんこれは誤りで、ちゃんと、vueのdata部をsetInterval内で書き換えるようにしたらいけました。
(すごいシンプルな間違い。)

シンプルにView(html)とModel(js)をバインディングしてくれて非常に楽ですね〜
(ReactとかRiotとか使ったことないので、もっと楽かもだけど。)

Date型から強制的に「年月日」以外のデータを切り捨てる

環境

つまづきポイント

Swiftで日付の差分を計算してその間の日数を表示するロジックを書いてたら Date型で時・分が保存されてしまっていて、想定外の日数となっていた!

// 現在日付を取得(例えば 2017/07/12 12:01)
let today_date = Date()
// 期限を取得(例えば 2017/07/22 12:00)
let deadline_date = settings.object(forKey: "deadline_date") as? Date
    
// 現在の残り日数を計算
var deadline_days_now = calendar?.dateComponents([.day], from: today_date, to: deadline_date).day
// ->日付だけ計算すると10日のはずだけど、時・分が保存されてしまっていて9日になってしまう!

解決方法

一旦、DateからDateComponentsにしてDateに戻す関数を作成して強制的に切り捨てた

// Dateから年日月を抽出する関数
func roundDate(_ date: Date, calendar cal: Calendar) -> Date {
  return cal.date(from: DateComponents(year: cal.component(.year, from: date), month: cal.component(.month, from: date), day: cal.component(.day, from: date)))!
}

// 現在日付を取得(例えば 2017/07/12 12:01)
let today_date = Date()
// 期限を取得(例えば 2017/07/22 12:00)
let deadline_date = settings.object(forKey: "deadline_date") as? Date
// カレンダーを取得
let  calendar = Calendar(identifier: .gregorian)

// today_dateから年月日のみ抽出する -> 2017/07/12となる
let today_date_rounded =  roundDate(today_date!, calendar: calendar!)
// deadline_dateから年月日のみ抽出する -> 2017/07/22となる
let deadline_date_rounded =  roundDate(deadline_date!, calendar: calendar!)


// 現在の残り日数を計算
var deadline_days_now = calendar?.dateComponents([.day], from: today_date_rounded, to: deadline_date_rounded).day
// ->時・分が保存されてないので正しく計算されて10日になる

複数ページある場合のアプリ起動時のローカル通知の処理の設定方法

環境

つまづいたところ

LocalNotificationを実装したところ、アプリ立ち上げ中に時間になってもまったくローカル通知がなかった…

解決方法

複数ページあるiPhoneアプリの場合、ローカル通知のdelegateはAppDelegateにかく! (一つのViewControllerにuserNotificationCenterのdelegateを書いてたため、通知に音沙汰がなかったようです…)

import UserNotifications

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

  var window: UIWindow?
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    
    //起動中に通知を受け取るためのdelegate設定
    UNUserNotificationCenter.current().delegate = self    
    return true
  }

// いろいろ書いてあるdelegateは省略...
  
  // アプリが foreground の時に通知を受け取った時に呼ばれるメソッド
 // AppDelegateの中にuserNotificationCenterのdelegateをかく!
  func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.alert , .sound])
  }


}


UINavigationContollerの自動生成される「戻る」ボタンの書き換え

環境

前提条件

メイン画面(ViewController.swift) → 設定画面(SettingsViewController.swift)

やり方 その1

遷移先であるSettingsViewController.swiftを書き換える。 今回はこちらを採用。

  override func viewDidLoad() {
    super.viewDidLoad()
    
    //トップに戻るボタンを作成
    let leftButton = UIBarButtonItem(title: "戻る", style: UIBarButtonItemStyle.plain, target: self, action: #selector(goTop))
    self.navigationItem.leftBarButtonItem = leftButton
  }

  func goTop(){
    //トップ画面に戻る。
    self.navigationController?.popToRootViewController(animated: true)
  }

やり方 その2

遷移元であるViewController.swiftからbackbuttonを書き換える。 (実装してないが、たぶんいけるはず?)

  override func viewDidLoad() {
    super.viewDidLoad()

    //トップに戻るボタンを作成
    let backButton = UIBarButtonItem(title: "戻る", style: UIBarButtonItemStyle.plain, target: self, action: #selector(goTop))
    self.navigationItem.backBarButtonItem = backButton
  }

  func goTop(){
    //トップ画面に戻る。
    self.navigationController?.popToRootViewController(animated: true)
  }
  

わからんポイント

その一だと「<」と書かれた矢印も合わせて書き換えられてしまう。 どうすればいいか。

Python + Heroku + LINE BOT SDKでコーランを教えてくれるbotを作った

LINE BOT AWARDSでLINE BOTが盛り上がってるので作成してみました。
LINE BOT AWARDSにも「ローカライゼーション」部門でエントリしておきました。
ほぼ一発ネタなので、暇つぶしにでもフォローしてみてください。

つくったもの

言葉に対してなんでもコーランの開端の章の一節を返してくれるbot
「意味は?」とか聞くとそのコーランの意味を教えてくれたりします。
こんな感じです。 f:id:pco2699:20170303145726p:plain

なぜつくったか

  • 最近 海外に出かけるときは、なにかと物騒なのでコーランを覚えておいたほうが安全なのでは、と思ったため
  • これをきっかけにイスラム教の人と仲良くなれるかな、と思ったため (まだイスラム教の友達はいないけど..)

利用したもの

ソースコードはLINE BOT SDKの中のサンプルsimple-server-echoをベースに作りました。
その他に利用したものは以下。

Github

github.com