これぞ、完全タッチレスエントリー

17日目の記事です。

WebエンジニアのBunです。主にiOSアプリの開発を担当しています。

ドアに貼り付けるだけでスマホICカード社員証、遠隔から施錠解錠可能な弊社のスマートロックAkerunについて、もっと楽な施錠解錠方法がないか日々考えています。

新型コロナウイルスが広がっている中、ドアすら触れたくないですね。そこで、Apple Watchと弊社の「タッチレスエントリー・ソリューション」を組み合わせて、完全タッチレスでより快適な解錠を実現してみたいと思います。

akerun.com

akerun.hateblo.jp

13日目の記事(LINE Botから施錠解錠する)も書いたので、こちらも読んでみてください。

akerun.hateblo.jp

大分前にApple Watch Series 2を購入しましたが、その時はまだWatchOSのバージョンが2か3になっていて、色々機能制限があったので、結局何も作らずにただの腕時計として使ってきました。 その後、だんだん制限が解除され、特にWatchOS 6から独立したアプリも作成できるようになったので、Apple Watchだけで解錠できるアプリを作ってみました。

※最新のSeries 6を購入しようと思いましたが、今持っているSeires 2でもWatchOS 6までアップデートできたので、新たに購入せず済みました。ラッキ~

基本的にWatchOSのCMDeviceMotionから取得した姿勢データとBLEを使って実現可能なので、試してみたら、予想より簡単にできてしまいました。

WatchOSアプリのプロジェクト作成

プロジェクト新規作成から以下の「Watch App」を選択します。

適宜内容を記載し、プロジェクトを作成します。

以下のフォルダ構成フォルダ構成になります。

今回は特にUIも必要ないので、主にExtensionの方を実装していきます。 ただ、最初はMotionセンサーとBLE処理をデバッグしながら作るので、WatchKit AppのUIにテスト用ボタンなど追加してデバッグを行います。 また、毎回ビルドしてApple Watchにバイナリを転送すると結構時間がかかるので、Akerun本体とのBLE通信を確認するためのiPhoneアプリ(BLETester)も作ります。

Akerun本体とのBLE疎通確認

AkerunはPeripheralとして動作するので、Apple WatchをCentralとして動作させます。 iOS同様WatchOSからも直接BLE通信ができるので、CBCentralManagerを使って、Scan、Connect、Write(解錠コマンド書き込み)処理を実装します。 解錠用BLEコマンドは独自の暗号化処理になっているので、詳細は割愛します。

Motionデータ取得

WatchOSのCoreMotionからattitude(姿勢)、rotationRate(角速度)、gravity(重力加速度)、userAcceleration(加速度)が取れますが、今回はシンプルにattitude(姿勢)を使います。

Attitudeはpitch(ビッチ)、roll(ロール)、yaw(ヨー)の姿勢角があります。 手の動きについて何パターンか考えましたが、ドアノブを回す動きが自然かなと思ったので、pitchの変化タイミングを検知し、適切な閾値を設定して、解錠判定を行います。 ちなみにpitchは以下の定義になります。

  • 時計の3時方向を右、9時方向を左にし、左右X軸に関する回転角
  • 値の範囲は -π/2 から π/2 まで
  • 腕を上げて、画面がActiveになる時は0

具体的に、腕を上げてpitchの値が0前後(+/-0.1)になったら、判定をスタートし、腕を一瞬反時計回りに回した時、pitchの値が-π/3前後で解錠コマンドを送信するようにしています。

Apple Watchは、腕を下げると画面がDeactiveになるので、センサー情報の取得とBLE通信ができなくなります。バックグランドで実行するタスクを作れば、一定時間動作しますが、今回はDeactiveにならないように腕を反時計回りに回した後すぐ戻すことで回避しました。

画面がActiveになった場合、以下でMotionデータ取得開始します。パフォーマンスも考慮して、データ取得Intervalは1/30以下で十分だと思います。

private var motionMan = CMMotionManager()

func start() {
    if self.motionMan.isDeviceMotionAvailable {
        self.motionMan.deviceMotionUpdateInterval = 1.0 / 30.0
        self.motionMan.startDeviceMotionUpdates(to: OperationQueue.current!) { (motion, error) in
            if let m = motion {
                let data = MotionData(
                    attiPitch: m.attitude.pitch,
                    attiRoll: m.attitude.roll,
                    attiYaw: m.attitude.yaw
                )
                self.delegate.motionMamanger(self, data)
            }
        }
    }
}

func stop() {
    self.motionMan.stopDeviceMotionUpdates()
}

Motionデータが定期的に通知されるので、pitchがπ / 20以内になったら解錠判定をスタートし、その後のpitchが反時計回りにπ / 3以上回ったら、Akerunに接続し、解錠コマンドを送信します。

extension InterfaceController: MotionManagerDelegate {
    func motionMamanger(_ motionManager: MotionManager, _ data: MotionData) {
        if fabs(data.attiPitch) < Double.pi / 20 {
            self.isActive = true
        }
        
        if self.isActive {
            if data.attiPitch < -Double.pi / 3 {
                self.isActive = false
                self.akerunMan.connect(to: testUuid)
            }
        }
    }
}

動作

ちょうど出社する日があったので、Officeのドアで試してみました。ドアには電気錠/電磁錠に対応したAkerunコントローラーが設置され、半年前にタッチレスエントリーも導入しました。

普段は社員カードをかざして入退室していますが、下記のようにほぼ完全タッチレスが実現できました。

f:id:photosynth-inc:20201216111241g:plain

※動画撮るために腕を前に出していますが、手首の部分を少し上げてから回しても問題なく動作します。

まとめ

久しぶりにWatchOSを触りましたが、やっぱりIoT製品との相性も良く面白いですね。WatchOSのMotionセンサー、BLEなど基本的な機能だけで簡単にアイデアを具体化できるので、今後も色々試して見たくなります。

ただし、iOSと違ってまだまだ色々制限があるので、工夫しないといけないところもあります。

  • バックグランド処理

画面がDeactiveになって、バックグラウンドに入った時は処理が実行されません。 今回は、腕を早く回すことで何とか回避できましたが、下記の拡張セッションを使えば、完全ではないですが、バックグラウンドでの処理が実行できそうです。

f:id:photosynth-inc:20201215152347p:plain https://developer.apple.com/documentation/watchkit/using_extended_runtime_sessions

WatchOS 8以降でバックグラウンドでも簡単に処理が実行できるようになるかもしれませんが、早めにこういう制限を解除して欲しいですね。

  • NW通信

WiFiモデルの場合、結局iPhone経由でNetwork通信を行うので、独立したWatchアプリではなく、「iOS App with Watch App」でも十分かもしれません。Cellularモデルであればもっと快適になるかと思います。

取り敢えず動作するかどうか試してみただけなので、精度についてはそこまで考えていません。 以下のモーション動作を分類するActivity Classificationを使ってモデル構築し、機械学習すれば、色んな解錠ジェスチャーが実現できて、精度がもっと上がると思います。誤動作も少なくなるはずです。

f:id:photosynth-inc:20201215152435p:plain https://developer.apple.com/videos/play/wwdc2019/426/

また別の機会で試してみたいと思います。


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 hrmos.co

Akerun Proの購入はこちらから akerun.com

メカ設計する時に重要だと思っている思考

この記事は Akerun Advent Calendar 2020 - Qiita の16日目の記事です。

はじめまして。株式会社フォトシンスでメカ開発・設計を担当しております y_nagnag - Qiita と申します。 2020年10月からこの会社で働き始めました。 Advent Calendar書いてみるか!と息巻いてみたものの「うーん、、何書こう?」と頓挫して早数週間。。。 結果、「せっかく記事にするのであれば自分のための備忘録的なものにしよう!」と考え、メカ設計に従事する上で私なりに重要だと考えていることを書くことにしました。

メカ設計って?

メカ設計って何やってるかよく分からないと言われることがありますが、例えるならば「自分でピースをデザインしてパズルを完成させるような行為」だと思っています。

製品の外観デザインや仕様からパズルの完成像は決まってきますが、それを実現するための部品であるピースは「無」の状態から始まります。そのため、パズルを完成させるためにどんな部品が必要か/どんな部品構成をとるべきかを、性能、強度、耐久性、量産性、価格、etc.から多角的な視点で捉えて考え、1つ1つピースを作っていかないといけません。高次元なパズルゲームだと思っていただけると、少しは興味が湧くかもしれません。

この高次元なパズルゲームを解くためには「物理現象を捉える/知る」「思考実験をする」「多角的に考え最適解を求める」ことが重要だと私は考えています。以降に述べていきたいと思います。

物理現象を捉える/知る

ハードウェアの部分を設計している以上は物理現象が常に付きまとってきます。そのため、必要最低限な知識として物理現象を知っておく必要があります。ここでいう物理現象とは落下すると衝撃を受ける、熱は上に逃げていく、光は屈折したり反射したりする、といった物理学の話です。ここが分かっていないとメカの設計はできません。

実際に部品を設計すると試作して部品の出来栄えや機能の確認をするのですが、試験していく中で何かしら問題が起きることがあります。例えば、30cm落下させた時にプラスチック部品にクラックが入ってしまったとか。ここで、問題の原因を特定をしなくてはならないのですが、現物/現場/現象の3つを正確に捉える必要があります(探偵みたいですね)。理由は単純で、現物/現場/現象の3つが揃うことで初めて問題が生じるからです。

今回の例えで話すと、

現物:プラスチック部品 現場:30cm落下させる 現象:??? 結果:クラックが発生

となります。

ここでは現象に当てはまるヒントは現場にありそうですね。大体の人は現場の「落下」から、現象は「衝撃である」と結びつけます。

このように3つを正しく結びつけることができれば原因の特定につながり問題解決の糸口になります。また、問題となった物理現象は表面的にではなく、本質的な部分で捉え上位概念化して知識として頭の引き出しにしまっておきましょう。そうすることで似たような問題が起きたときに対処しやすくなり、別の製品や部品を設計する時に失敗しづらくなります。

思考実験をする

物理現象が伴ってくる以上は現物で確認する必要があります。メカ設計者の中には「とりあえず試作しよう!」ってタイプの人がいると思いますが、私はこの考えに割と否定的です。なぜなら、大抵このパターンは捉えるべき物理現象をあらかじめ把握できておらず無意味な試作になる場合が多いからです。そのため、試作をする前には質の高い思考実験を必ずするべきだと考えています。思考実験とはなんぞやって話になりますが、頭の中で実験場を展開しイメージ実験をすることです。

思考実験をする際のポイントとしては「深い思考を短時間に」です。

深い思考は前項で述べた上位概念化できている物理現象の知識量によって質が決まってくると思います。なぜなら、想像上で展開できる物理現象の引き出しが多いほど現実に則してくるからです。自身の思考実験が現実と一致するレベルまでできていると質が高いと言えるでしょう。

時間をかけてはいけない理由は一つの現象にのめり込んでしまい視野狭窄に陥りやすいからです。メカ設計は高次元のパズルゲームであるため、1次元だけにフォーカスしていては成り立たちません。常に多角的に捉えるためのポイントとして、「あえて時間をかけない」という方が正しいかもしれません。

思考実験を経て「確証が得られる」or「これ以上は分からない」レベルになった時点で実際のシミュレーションもしくは試作に踏み切って確認するようにしましょう。これによって、無駄な試作にかける時間とお金を節約できますし、何よりも確認しなくてはならないことがハッキリするので、効率的かつ効果的に試作を実施することができると思います。

また、試作確認の際に想定外の問題が起きた場合は前項で述べたことを経て知識のアップデートをしましょう。そうすることで、次回からの思考実験の質が上がっていくと思いますし、品質トラブルを起こしにくい設計ができるようなってくると思います。

多角的に考え最適解を求める

メカ設計は高次元なパズルゲームだと述べさせていただきました。高次元である以上、多角的に捉えて思考しなくてはなりません。この時に、絶対にやってはいけないという訳ではないんですが、設計した部品に対して「正解/間違い」の2値で考えてはいけないと私は思っています。理由は自由度の高さ故に唯一解は基本的に出てこないからです。

1つの次元だけで考えれば「正解/間違い」の2値で考えて良いのかもしれません。例えば、強度という面だけで考えれば十分に満足しているので正解ですと言えるかもしれません。 しかし実際には性能、耐久性、価格、など多角的に捉えていくと全てにおいて正解という訳ではないことに気がつきます。1つ1つの次元で良し悪しを持ったグラデーションのある解になっている場合が多いです。

そのため、出てきたグラデーションのある解の良し悪しは、製品が晒される環境において最適であるか否かで判断するべきだと私は考えています。 「正解を叩き出す」というよりは「あらゆる次元で通用する最適解にもっていく」という考え方で臨んでいる方が常に多角的に捉えられるので問題を起こしにくいです。上述した思考実験にも通ずる話になります。

製品が晒される環境は規格として握られてる場合が多いですが、できればお客様が使用されている現場に赴いて確認し、製品が晒される環境がどういった状況なのかを自身の中でしっかり握っておくことが大事です。

またもう一つポイントとして、多角的に考える際に「製品の未来像」や「市場問題が起きた時のバックアッププラン」も含めて考えれるとベストです。「今の流れから察するにこの製品の未来はこうかなぁ」「製品規格上満足しているけど、こんな問題起きないだろうか」という観点も含めて考えておくと、市場から出てきた要望やトラブルに対して迅速に対応できる仕掛けをあらかじめ製品に組み込んでおくことができます。

まとめ

つらつらと長く書いてしまいましたが、まとめるとこんな感じです。

  • 物理現象が伴ってくるので現物/現場/現象を真摯に捉えることが非常に重要。生じている物理現象は上位概念化し知識にして頭の引き出しにしまう。

  • 無意味な試作よりも思考実験を。そして深い思考を短時間で。時間をかけるほど視野狭窄に陥りがち。メカ設計における深い思考は、上位概念化できている物理現象の知識量で質が決まる。確証が得られる or これ以上は分からないレベルになった時点でシミュレーションもしくは試作に踏み切って確認する。

  • 正解/間違いの2値で解を求めるのではなく、多角的に考えて最適解を導き出すよう努める。多角の中には製品の未来像や市場問題が起きた際のバックアッププランも見据えて考えられるとベスト。

「あれ?3D CADの使い方は?図面の書き方は?」と思われた方もいるかと思いますが、実際にCADや図面の書き方は設計思想を表現するツールでしか無いと考えています(それ故に重要ではあるのですが今回は割愛)。

メカ設計のベースとなる部分は上記で述べたようなところになってくると考えており、私自身が実践できている/できていないが確認できるように記事としてしたためさせていただきました。

私の記事が少しでも皆さんのお役に立てれれば幸いです。


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 hrmos.co

Akerun Proの購入はこちらから akerun.com

選定した電気部品が買えなくなった時の話

この記事は Akerun Advent Calendar 2020 - Qiita の 15 日目の記事です。

はじめましてPsFujiです。
フォトシンスの開発部で電気回路設計を担当しています。
自分の文章を大勢の方に見ていただくのは初めてなので結構緊張しています。

弊社製品に関する事で何か面白いことを・・・と言われました。
何しろ入社2か月足らずのシニアな新入社員なのでネタに困りました。
困った結果、製品開発でよくある事について書こうと思います。

〇選定した電気部品が買えなくなった時の話


発生してほしくはないですが、狙ったかのように嫌なタイミングで発生するのが部品供給問題です。

”初ロット”

”ちょロット”

な挙句

” 総ロット”

になる


こういった製品なら問題ありません。
しかし、長期間にわたり製造する製品にとっては、非常に大きな問題となります。

部品が買えなく(入手難も)なったとの連絡を受けた後に取る主な対応は
以下の様な物になると思います。
    1)部品メーカーにお願いして最後のまとめ生産してもらう。
    2)回路やソフトの設計変更で別部品対応をする。
    3)市場にある流通在庫品を購入して対応する。
    4)聞かなかった事にして家に帰る。

今回お話するのは 3) の流通在庫品に関してです。

・製品を生産する段階になった時、ある部品が入手できないとの連絡が入りました。
開発日程を考えると今から設計変更する時間はないし、完全互換な代替品もない・・・・
となると取る方法は一つ、

"市場流通在庫品”

の購入です。


ネットで色々調べたところ市場在庫品を見つけたので聞き取り調査開始。

〇在庫確認

 私)在庫有る?

 商社)すぐに発送できるよ~

〇見積もり確認

 私)おねだんいくら?

 商社)これが見積もりだよ~

〇品質対応確認

 私)偽物だったり故障品だったりしないよね?

 商社)クレームあれば1か月以内に連絡くれれば返金対応するよ~

うん、レスポンスもなかなか早いし対応もそこそこ。
じゃあ、まずは少量入手して動作確認、問題なければ大量購入しよう と連絡をした所

〇現物確認

 私)有償でもよいから10個購入したいんだけど

 商社)じゃあ、1000USD前払いね。

・・・・・・え?


 私)見積もりと違うじゃん?

 商社)前払い必須、最低金額1000USDだから。それと自国の企業とは商売しないから

〇メールでは埒があかないので電話確認

 商社)出張中で電話取れないから!(メールで返答)


なんだか雲行き怪しくなってきたぞ・・・・・という事で色々調べていたら悪い評判たくさんできてきました
 ・金を振り込んだのに物が来ない
 ・詐欺だ
 ・ペーパーカンパニー
 ・金を振り込んで後悔した
 ・・・等 たくさん出てきました。

心配になったのと、でも部品は入手したいという事で

〇事実確認

 私)なんかネット上で悪評多いから心配になったけど、ちゃんと電子部品購入できるの?

 商社)・・・・・ごめん!在庫無いから売れない

以後、返事をもらえなくなりました。

〇教訓〇

”旨い物食わす人に油断すな”、困っている時ほど慎重に



過去には、流通在庫品のチップ部品を購入した時、日本メーカーの部品だからと安心していたら・・・
・リール内のコンデンサの容量がバラバラ
・メーカーに確認した所、リールに記載されているメーカ型番は正しいがLOT番号は存在しない番号だった。

なんて事もありましたが、それはまたの機会にでも・・・・



株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 hrmos.co

Akerun Proの購入はこちらから akerun.com

クロス開発を快適に 〜バイナリと仲良くなるためのTips〜

この記事は Akerun Advent Calendar 2020 - Qiita の14日目の記事です。

ishturk - Qiitaです。

f:id:photosynth-inc:20201214104136j:plain

弊社はIoT企業なので、プログラムを書くエンジニアも、Web、スマホアプリ、マイコン、サーバー、インフラなど多岐にわたります。 これまではキャリア採用で、組込みのベーシックな知識がある人がジョインしているのですが、最近はWebからコンバートして組込みをやるエンジニアもいたり、新卒が入る予定もあったりして、組込み界隈のTipsやらをまとめようとしています。

今回は特にハードルが高いと思われがちなC言語を使ったクロス開発について。

クロス開発とは?

プログラムの開発環境と実行環境が違う開発で、特にプログラムのコンパイルが必要な場合を指します。

クロス開発の開発環境

多くの場合、 - コンパイラやリンカと便利ツールをセットにしたツールチェーン - ツールチェーンを内包した統合開発環境 で構成されます。始めるときや必要な情報をggるときは 「XXX(ターゲット) toolchain」とすると記事が沢山でます :)

バイナリと仲良くなるためのTips

参入障壁になりがちなのがここで、バイナリという言葉にアレルギー反応を起こす人も多いのでは。ポインタでつまづいた人は、バイナリとも喧嘩するでしょう。

コンパイラが生成するファイルたちについて理解する

  • .o ファイル :Cのソースをコンパイルしてできるバイナリ。1つの.c から同名の.oができると思って良い。ObjectのO。
  • .a ファイル: .o をまとめてできたファイル。SDKからライブラリとして提供される場合、ソースが提供されずに .a ファイルが提供される場合も多い。Archive のa。
  • .bin、.hex、.elfファイル:プログラムのバイナリそのもの。情報量は bin < hex << elfの関係。 .binはデータのみ。.hexは書き込みアドレス+データの方式でbinのデータをマッピングしたもの。.elfはシンボル情報などの付加情報が含まれている。
  • .mapファイル:デバッグ用の情報がまとめられているファイル。

バイナリを覗いてみる

玄人組込みエンジニアがバイナリが読めるなんていう都市伝説があります。16進数の羅列からほんとによめる猛者もいますが。。。ここはツールを使いましょう

この記事では詳細については書かないので、こんなツールがあるんだ!と知るきっかけになって貰えればと思います。

ツールについて

クロス開発では、コンパイラアーキテクチャが開発マシンと違うのでOSでインストールされているツールは使えないことが多いです。 最初に書いたツールチェーンに含まれている(はず)ので、探しましょう。コンパイルするためにパスを通したディレクトリにあります。

armのツールチェーン

f:id:photosynth-inc:20201214081824p:plain

ESP32のツールチェーン

f:id:photosynth-inc:20201214081840p:plain

nm

nm を実行すると、オブジェクトファイルのシンボル情報を確認できます

試しにESP32のhello worldをみてみましょう

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"

void app_main(void)
{
    printf("Hello World");
}

f:id:photosynth-inc:20201214083015p:plain

main.c から生成した main.c.o は非常にシンプルです。

f:id:photosynth-inc:20201214083340p:plain

実行バイナリだとシステム起動などがあるので壮大になりますが、例えば main でgrep すると

f:id:photosynth-inc:20201214083454p:plain

app_main が 400d151c 番地 にマッピングされていることがわかります

odjdump

オブジェクトファイルから情報を引き出すツールです。いろいろできるのですが、逆アセンブルするときによく使います。

f:id:photosynth-inc:20201214084718p:plain

l32r は32bitのロード命令ですね。printするためにメモリに値をコピーしているのでしょう。

この方法を使えば、バイナリしか提供されていないオブジェクトファイルのアセンブラコードをみることができます。SDKの動きでハマった場合に有効です。

※ ライセンスによっては逆アセンブルが禁止されている場合もあるのでご注意を

addr2line

アドレスからソースコードの行数を表示するコマンドです。

先程の app_main が 400d151c 番地だったので、ためしにこれを逆引きしてみます。

f:id:photosynth-inc:20201214085601p:plain

app_main 関数で、9行目であることがわかりました。

これを使うユースケースは、例えば実行中にsegmentation faultが起こって、落ちたアドレスが情報として得られた場合、ソースコードのどの箇所なのかを引くことができます。

readelf

elf ファイルのヘッダ情報などをみることができます。 セクションヘッダ、プログラムヘッダなどの言葉を知ったら見てみてください。

ツールチェーン以外のツール

mapファイルを見る

コンパイラがmapファイルを吐いてくれる場合、ここにデバッグに有用な情報が沢山かかれています。 ↑でバイナリから取得した関数のマッピング情報なども実はここにすべてかかれています。

xxdコマンド、vimmerなら :%!xxd

バイナリを16進数方式 | ascii エンコードの方式で表示します。意味不明に見えますが、ここから関数名や変数名がみえたり static const の定数が探せたりします。

また、バイナリの差分を見るときはvimdiff + xxd で見ます(どや

おわり

「クロス開発コワイ」を減らす一助になれば幸いです。

この中のひとつでも知ってると「組込みやってる感」がでるので試してみてください!


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 hrmos.co

Akerun Proの購入はこちらから akerun.com

Why Quality Assurance?

この記事はAkerun Advent Calendar 12日目の記事です。

はじめまして。株式会社フォトシンスでQAエンジニアに従事しているyohei_oka - Qiitaと申します。
早速ですが、QAエンジニアという職種をみなさんはご存知でしょうか?
私はQAエンジニアからIT業界をスタートし、これまでに様々なプロダクトのQAに携わってきました。
その中で私が学んだこと、培ったことを元に、私がQAについて考えていることを少しお話したいと思います。

1.QA(Quality Assurance/品質保証)エンジニアの役割とは

一般的にQAエンジニアというと「品質を向上させる役割」というイメージを持たれているかもしれません。
単刀直入にお伝えします。我々QAエンジニアがいても、品質は向上しません。
もちろん間接的には寄与しますが、我々の存在だけでは品質を向上させることはできない、という意味です。
我々ができるのは「品質の可視化」です。品質状況を可視化し、その品質が合格水準に達しているかどうかの判定をするのが、我々の本来の役割です。
では、品質を向上させるのは誰の役割なのでしょうか?

2.品質とは何を指すのか

品質向上について考える前に、そもそも品質とは何を指すのか考えたいと思います。
我々が品質について考える時、実はそこには二種類の品質が存在します。

  1. プロダクトの品質
  2. プロジェクトの品質

一般的には、1のプロダクトの品質に着目されがちですが、実は2のプロジェクトの品質も同じくらい重要です。
プロダクトの品質は、顧客の満足度に直結します。逆に言えば、顧客満足度の最大化をミッションとし、我々はプロダクトの品質を考えます。
これに対し、プロジェクトの品質というのは、開発効率を意味します(広い意味での効率と捉えてください)。開発効率の最大化が、プロジェクト品質を考える上でのミッションです。

エンジニアは誰しも、品質の悪いものを作ろう、とは当然思いません。
しかし、それでも完成したプロダクトの品質が悪かった時、それは、プロジェクトのどこかに何らかの問題があった、ということになります。
逆に言えば、プロジェクト品質の向上なくして、プロダクト品質の向上はありません。

つまり、品質を向上させるのはプロジェクト全体の役割である、ということです。
マネージャーはもちろんのこと、エンジニア含むプロジェクトメンバー全員の意識が品質に向いて、初めて品質は向上していきます。
二つの品質向上にアプローチするための要となるという点で、QAエンジニアは重要な役割を担っていると考えています。

3.QAとは技術ではなく思想である

QAエンジニアにできるのは「品質の可視化」である、というのは前述した通りです。
しかしながら、それだけで良い、とは私も思っておりません。

これからのQAに求められるのは、その一歩先。可視化されたデータを元にプロダクト/プロジェクトの課題を見抜き、それらを解決していく、その活動の先頭に立つことです。
プロダクトに不具合が発生したならば、不具合の原因は何なのか、という直接的な原因はもちろんのこと、そもそもなぜ不具合が発生してしまったのか、という根本的な原因も究明し、可視化させなくてはいけません。可視化したデータを元に、プロジェクトにフィードバックし、双方の品質改善にアプローチしていくのが、これからのQAエンジニアの役割です。

だからこそ私は、QAとは技術ではなく思想であると思っています。
極端な話、QAエンジニアがこれでいいと思ったところまでしか、品質は上がりません。
基準を低く設定してしまえば、それ以上を目指そうとは誰も思わないからです。
逆にQAエンジニアが志を持って高い基準を目指せば、その分だけ品質は上がっていきます。
だからこそ、必要なのは姿勢であり、思想である、と私は考えます。

そんな志を持ったQAエンジニア、これからの時代にいかがでしょうか?


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 hrmos.co

Akerun Proの購入はこちらから akerun.com

脆弱性対応情報データベース (MyJVN API) の API を使って OSS の脆弱性を見てみる

この記事は Akerun Advent Calendar 2020 - Qiita の 11 日目の記事です。

今週 2 回目の登場です。 AkiAbe - Qiita です。
前回は、スプリント開発の話でマネジメント寄りの話でした。 akerun.hateblo.jp

今回は、少しテック寄りにしようと思います。

OSS脆弱性の情報確認

この記事読むようなかたは、Open Source Software (OSS) については把握していますね。
意識の高いエンジニアのみなさんとしては、自分が使っている開発環境の OSS脆弱性がどんなものあるか把握しておきたいですよね。

OSS脆弱性はデータベース化されています。
jvndb.jvn.jp

たとえば、debian 系 OS で、sudo コマンドの脆弱性はどのようなものがあるか調べてみましょう。

JVN iPedia - 脆弱性対策情報データベース
JVNDB-2019-014477 - JVN iPedia - 脆弱性対策情報データベース

JVNDB-2019-014477
Sudo における境界外書き込みに関する脆弱性

という指摘がでてきました。

こんな感じで、自分の環境のどのパッケージにどんな脆弱性があるかを調べることができます。

API を利用して、まとめて調べたい

ひとつずつパッケージ名入れて検索するの面倒ですよね。
MyJVN API という API が公開されているのでそれを利用してまとめて調べられないか試してみます。

私は試しに手元のラズパイでやってみます。
これから使うラズパイの OS 情報です。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 9.13 (stretch)
Release:    9.13
Codename:   stretch

$ uname -a
Linux rpiTester 4.19.66-v7+ #1253 SMP Thu Aug 15 11:49:46 BST 2019 armv7l GNU/Linux

ためしに、前述した sudo コマンドを API を叩いて調べてみます。
JVNDB-2019-014477 の指摘が得られます。 (それ以外のも得られます)

$ curl -G -d "method=getVulnOverviewList" -d "feed=hnd"  -d "keyword=sudo" -d "datePublicStartY=2019" -d "rangeDatePublished=n" -d "rangeDateFirstPublished=n"  https://jvndb.jvn.jp/myjvn

<?xml version="1.0" encoding="UTF-8" ?>   
<rdf:RDF 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://purl.org/rss/1.0/" 
xmlns:rss="http://purl.org/rss/1.0/" 
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
xmlns:dc="http://purl.org/dc/elements/1.1/" 
xmlns:dcterms="http://purl.org/dc/terms/" 
xmlns:sec="http://jvn.jp/rss/mod_sec/3.0/" 
xmlns:marking="http://data-marking.mitre.org/Marking-1" 
xmlns:tlpMarking="http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1" 
xmlns:status="http://jvndb.jvn.jp/myjvn/Status" 
xsi:schemaLocation="http://purl.org/rss/1.0/ https://jvndb.jvn.jp/schema/jvnrss_3.2.xsd http://jvndb.jvn.jp/myjvn/Status https://jvndb.jvn.jp/schema/status_3.3.xsd" 
xml:lang="ja">
    <channel rdf:about="https://jvndb.jvn.jp/apis/myjvn">
      <title>JVNDB 脆弱性対策情報</title>
      <link>https://jvndb.jvn.jp/apis/myjvn</link>
      <description>JVNDB 脆弱性対策情報</description>
      <dc:date>2020-12-07T17:58:27+09:00</dc:date>
      <dcterms:issued/>
      <dcterms:modified>2020-12-07T17:58:27+09:00</dcterms:modified>
      <sec:handling>
        <marking:Marking>
          <marking:Marking_Structure xsi:type="tlpMarking:TLPMarkingStructureType" marking_model_name="TLP" marking_model_ref="http://www.us-cert.gov/tlp/" color="WHITE"/>
        </marking:Marking>
      </sec:handling>
      <items>
        <rdf:Seq>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-014477.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-013632.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-013631.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-011719.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-011096.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-010626.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-007171.html"/>
          <rdf:li rdf:resource="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-005598.html"/>
        </rdf:Seq>
      </items>
    </channel>
    <item rdf:about="https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-014477.html">
      <title>Sudo における境界外書き込みに関する脆弱性</title>
      <link>https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-014477.html</link>
      <description>Sudo には、境界外書き込みに関する脆弱性が存在します。</description>
      <dc:creator>Information-technology Promotion Agency, Japan</dc:creator>
      <sec:identifier>JVNDB-2019-014477</sec:identifier>
    .....
    .....
    以後、省略

スクリプト

dpkg -l で、入っているパッケージ一覧がとれるので、それで取得できるパッケージに対して、上記の API脆弱性を確認してみます。

$ dpkg -l 

Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                            Version                           Architecture Description
+++-===============================-=================================-============-===============================================================================
ii  adduser                         3.115                             all          add and remove users and groups
ii  adwaita-icon-theme              3.22.0-1+deb9u1                   all          default icon theme of GNOME
ii  alsa-utils                      1.1.3-1                           armhf        Utilities for configuring and using ALSA
ii  apt                             1.4.10                            armhf        commandline package manager

    .....
    .....
    以後、省略

check.sh とかいう名前で以下のようなスクリプト作成します。
結構力技で書いてます... ^^;

#! /bin/bash

FEED="feed=hnd&"
MET1="method=getVulnOverviewList&"
URL="https://jvndb.jvn.jp/myjvn?"

# 2015 年以降で指摘があったパッケージを検索
START="datePublicStartY=2015&"
RANGEP="rangeDatePublished=n&"
RANGEF="rangeDateFirstPublished=n&"


RES_TMP_FILE="res_tmp.txt"

# 最初にみつけた指摘だけ出力する
res_check () {
    res_flg=1
    html_list=""
    
    while read str; do
    if [ "`echo $str | grep '該当する脆弱性対策情報はありません'`" ]; then
        res_flg=0
        break
    fi
    if [ "`echo $str | grep html`" ]; then
        html_list=$str
        break
    fi
    done < $RES_TMP_FILE

    echo $res_flg $html_list
    return
}



# パッケージリスト取得して、不要な文字列消す             
FILE_NAME="hoge.txt"
NEW_FILE="oss_list.txt"

dpkg -l > $FILE_NAME
sed -e 's/ii  //g' $FILE_NAME > $NEW_FILE


# package 名で web api 叩いて確認
while read Line; do

    # package 名抽出
    CHECK_PKG=` echo $Line | awk '{sub(" .*", "");print $0;}' `

    # "|" とか "||" とかの行をはぶく  
    if [[ $CHECK_PKG =~ ^[a-z].*$ ]]; then

        # keyword にパッケージ名指定して web api たたく 
        KEYWORD="keyword=${CHECK_PKG}&"
        curl -s ${URL}${MET1}${FEED}${KEYWORD}${START}${RANGEP}${RANGEF} > $RES_TMP_FILE

        # 返答解析する                                                                                                         
        ret=$(res_check)
        flg=`echo $ret | cut -c 1`

        if [ $flg -eq 0 ]; then
            echo "${CHECK_PKG}, 脆弱性報告なし "
        else
            tmp_url=`echo $ret | grep -oE 'http(s?)://[0-9a-zA-Z?=#+_&:/.%-]+'`
            echo "${CHECK_PKG}, 脆弱性あり (詳細確認してください), ${tmp_url}"
        fi
    fi


    
done < $NEW_FILE

rm -fr $FILE_NAME
rm -fr $NEW_FILE

実行してみる。

$  ./check.sh  

adduser, 脆弱性あり (詳細確認してください), https://jvndb.jvn.jp/ja/contents/2016/JVNDB-2016-006807.html
adwaita-icon-theme, 脆弱性報告なし 
alsa-utils, 脆弱性報告なし 
apt, 脆弱性あり (詳細確認してください), https://jvndb.jvn.jp/ja/contents/2020/JVNDB-2020-005502.html

    .....
    .....
    以後、省略

まとめ

上述のスクリプトは文字列でひっかけただけなので、意図してない指摘*1も含まれてしまいます。
うまいやり方は他にもありそうですが、見るものを絞ることはできた感じですね。
気になるパッケージの脆弱性があれば、自分でパッチを当てましょう。


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 hrmos.co

Akerun Proの購入はこちらから akerun.com

*1: https://jvndb.jvn.jp/ja/contents/2016/JVNDB-2016-006807.html なんかだと adduser パッケージ自体の指摘ではない

新卒エンジニアの学びと叫びと反省

この記事は Akerun Advent Calendar 2020 - Qiita の10日目の記事です。

はじめに

こんにちは、 私は今年の1月にPhotosynth初の新卒として入社しました。
普段はWebエンジニアとして開発を行っています。
初のAdvent Calendarなので、イケイケな技術を投稿!
といきたかったのですが何も思いつきませんでした...。

なので今回は1年弱を通して「学」んだことや「叫」びたいこと、「反省」したことを書きたいと思います。

学: 先輩エンジニアの行動は真似る

上達への近道は真似ることだと思います。
例えば

  • 議事録の取り方
  • ミーティングの進め方
  • コードレビューの仕方
  • コードの書き方

などなど、挙げればキリがないですね。
そんな学びを得た私ですが、真似る際に一点注意したことがあります。
それは 最初からコツを聞かない ということです。

取りあえず真似てみて、自分に合うかどうかを分析することは大切だと思います。
そしてコツを得るための思考や経験は間違いなく成長です。

観察する → 真似る → 試行錯誤する → コツを聞く → 試行錯誤する
→ 自分なりにアレンジする → 自分のものにする

今の私は上のフローがとてもしっくりきています。
皆さんも自分なりのやり方を見つけてみてください。

一点だけ補足ですが、「絶対に最初からコツは聞くな!」と言ってるわけではないです。
「真似するにしても難しい」と思った時は遠慮なく聞いてください。
大抵の人は聞かれてちょっと嬉しいと思います。

叫: Slackのスタンプは想像以上に嬉しい

入社一年目は不安も多く、常に焦りながら仕事をしています。
Slackに投稿する内容が無茶苦茶だったり、論点がズレていたり・・・。
ちょっとした謝罪の投稿に対してノーリアクションだと死ぬほど辛いです。
「がんばれ」のスタンプをくれるだけでとても救われます。
リリースした時も同様ですね。
リリースしたのにノーリアクションだと複雑な気持ちになります。
「おつかれ」スタンプの効果は偉大です。
リモートワークが基本になって直接会話をする機会が減ったからこそ、大事にしたいと思いました。
(スタンプをください!!!!)

反省: イエスマンになってしまっていた

ほとんどの新卒生は期待に応えようと必死に仕事をしていると思います。
私は期待に応えようとするあまり、取りあえず「はい!」と言ってしまっていました。

  • 相手の言っていることがイマイチ伝わってないのに「はい、わかりました」
  • 出来そうにないのに「はい、できます」

これは 「期待に応える」ではなく、「期待させている」 のです。
後になって「わかってないじゃん!」とか「出来てないじゃん!」と裏切ることになります。
なので、

  • わからないことは「ちょっと伝わらなかったので、もう一度説明してくれますか?」
  • 出来そうにないことは「出来ません」

とはっきり伝えましょう。
どこまで相手に期待するかは人によって様々ですが、私は「言われたことは全て期待されている」と思い込みイエスマンになっていた気がします。
今となっては自分の意思をはっきり伝えることも、実は期待されていたんだなと思います。

さいごに

同じく新卒生の方や、就職間近でドキドキしている学生さんの助けになれば幸いです。
来年はイケイケな技術について投稿するぞ!

株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 hrmos.co

Akerun Proの購入はこちらから akerun.com