Quantcast
Channel: 懒得折腾
Viewing all 764 articles
Browse latest View live

盘点 OSX 上最佳的 DevOps 工具

$
0
0
  • 推荐 0 推荐
  • 收藏 22 收藏,324 浏览

【编者按】对于运维人员来说,他们往往需要各种各样的工具来应对工作需求,近日 Dustin Collins 通过「The Best DevOps Tools on OSX」一文对 OSX 平台上的工具进行盘点。本文系 OneAPM 工程师整理翻译。

以下为译文

如果你供职于一个 DevOps 团队,那么肯定会用到很多工具,比如通讯、架构、编排、编程、测试等等。笔者总是关注一些热门工具,这样就能一直跟随潮流。笔者工作中使用的就是 Macbook Pro,因此本文列出了一些经常使用的工具,以及一些使用工具。

协作方面

Slack——沟通(内部或对外),还支持 Github、Jenkins 和 Pingdom 的推送通知。

Google Drive——分享设计文档/电子表格/演示文稿(内联注释十分强大)。

Google Hangouts——用来举行日常简短的视频会议及其他会议。

Screenhero——协作编程工具:双方都能控制鼠标/键盘,是笔者所发现当下诸多工具中体验最稳定的。

asciinema——终端录制与屏幕分享工具。尤其适合分享 CLI 工作流与创建教程。试试 rec 命令中的-w flag,对长期运行的命令支持良好。

ngrok——建立到本地主机的安全通道。在修改本地 API 或站点后,笔者在发布前一般会通过它进行分享并获得反馈,对缩短设计工作的反馈环节非常有效。

mac2imgur——将截屏上传到 imgur.com,比发送文件存到桌面上要好太多了。一旦上传后,就会将 imgur URL 自动复制到剪贴板上。

keen.io——用来追踪时间段发生的一系列事件,比如 Github 下载的开源项目。Keen 使得代码可以更清晰的可视化,取代盲目猜测。

Mou——撰写可实时预览的 Markdown 文件。在将 READMEs 文档推送到 GitHub 之前,使用 Mou 进行编写是个不错的选择。

开发方面

iTerm2——比默认的 Terminal app 要好得多,可以拆分 panes、search、instant replay 等。这里使用的是 Pastel(黑色背景)的配色方案。

zsh——比旧 OSX 自带的 bash 好用,可以用于结束 tab、自动安装插件,并易于定制。通过 homebrew 执行 zsh 的安装命令 brew install zsh,再将 oh-my-zsh 添加到顶层,就全部搞定了。

mackup——将配置文件备份到 Dropbox 上,这样一旦换新机器了,就无需数天时间,而是仅仅一个小时就能配置好开发环境。

CakeBrew——图形化管理 homebrew 的工具。笔者安装了很多 homebrew 安装包,而图形用户界面显然更好理解。

docker-machine——使用它来建立 VirtualBox 虚拟机从而运行 Docker 服务,也可以在 OSX 上安装 Docker 客户端。之前用的是 boot2docker,不过将来都会改用 docker-machine 了。

Vagrant——如果个项目不是运行在 Docker 上,那么就是运行在 Vagrant 虚拟机上。

ChefDK——在 Conjur,chef-solo 被大量使用,使用它整合工具非常方便。在这些工具中笔者最喜欢的就是 test-kitchen,它不止适用 Chef。比如,可以给 Docker 容器配置一个 shell 脚本,并对其运行测试。test-kitchen 可用来管理测试机器的生命周期。

packer——构建 AMI 的首选工具,比 vagrant-aws 插件更为轻量级。

RubyMine——vim 还是 emacs?都不是首先。RubyMine 的 debug 功能非常棒,可以远程连接 Ruby 编译器(Vagrant 或者 Docker 实例)。Chef 插件也很不错。

PyCharm——很棒的 debug 工具,集成了 IPython notebook。笔者使用过每一种 Python IDE,最终在前几年选中了它。

Sublime Text 3——对于规模较小且非 Ruby/Python 项目,它是默认编辑器。GoSublime 插件配置起来有点复杂,但是在写 Go 代码时会更简便。Conjur 已经开始使用 Jenkins Job DSL 插件,因此也会 Sublime 来写 Groovy 代码。

CheatSheet——CheatSheet 在后台运行,长按 command 键就能显示当前应用的快捷键列表。

Rested——man curl,查看 flags。笔者使用 Rested 浏览测试 API,有时候会保存请求,稍后做回归测试时进行回放。httpie 也是个很不错的备选。

Patterns——用来复查正则表达式,支持多种语言,还有内置的 cheat sheet。

其他

盘点OSX上最佳的DevOps工具

OneAPM–专业的应用性能的监控工具,能够实时展现整个系统的业务拓扑图,帮助进行故障的预警和定位,减少业务系统维护的工作量,协助开发和运维人员持续性的优化代码。

盘点OSX上最佳的DevOps工具

RescueTime——用来追踪不同应用上每周所花费的时间,也可用于评估工作时各种工具对于产效的影响。

Yoink——让文件拖拽更简便:Generate CloudFormation json -> Yoink -> AWS console

Evernote——在查看会议视频或者阅读科技书籍时做笔记。用过不少工具,不过最终还是选择了 Evernote。

原文链接:The Best DevOps Tools on OSX



React Native for Android 实践 —实现知乎日报客户端

$
0
0

React Native for Android 实践 — 实现知乎日报客户端

React Native for Android 的发布,对一个 Android 开发者来说还是有相当的吸引力的。通过前面这篇博客:React Native for Android 入门老虎好不容易入了门了,然后想找一个简单的项目,来练练手。一方面来熟悉一下 RN(React Native, 后面都做此简写),另一方面来验证使用 RN 来实现一个相对完整的项目的可行性。

平时用的最多的客户端之一:知乎日报,这个 APP 相对简单,而且也找到了有人分析的知乎日报 API 分析。就选择它了:实现一个 React Native 版的知乎日报客户端,目标是尽量实现官方客户端一致的效果。

这篇文章主要讲使用 RN 来实现知乎日报客户端的可行性和实现方法。整个项目开源在 GitHub 上:ZhiHuDaily-React-Native,欢迎 Star 和 PR。

基本概念

这里以我的个人理解,快速过一下 React Native 中一些基本概念。如果和官方的理解有些偏差,还请指出。

1. 组件

React Native 主要是通过 Virtual Dom 来实现显示页面或者页面中的模块。可以通过 React.createClass() 来创建自己的 Dom,在 React 中称之为组件(Component)。创建之后,就可以直接像 HTML 标准标签一样使用了。如下:

var MyCustomComponent = React.createClass({
    ...
});

// 然后就可以这样使用
<MyCustomComponent />

到底什么是一个组件?我的理解就是页面上的一个逻辑单元。组件可以小到一个按钮,也可以大到整个页面,组件嵌套组合,就成了各种复杂的界面了。

2. 组件生命周期

类似于 Android 中的一个 View,它也有自己的生命周期,有自己的状态。React 组件的数据保存在自己内部的 state 变量中。每个组件都有自己的生命周期,每个生命周期都有对应的回调,这个和 Android 中的 View 非常类似:

  • getInitialState:获得初始化组件状态,只调用一次
  • componentWillMount:组件将要加载,只调用一次
  • componentDidMount:组件加载完成并显示出来了,也就是完成了一次绘制,只调用一次
  • render:绘制组件,可能调用多次。

具体要写自己的页面的话,要从哪里入手呢?我们这里就要来看一下React.createClass() 是什么的。这个方法可以辅助你创建一个组件,其中传入创建组件的参数,就是自定义组件需要的内容。一个基本的自定义组件写法如下:

var MyCustomComponent = React.createClass({
    // 这里返回一个对象,设置组件的初始化状态,
    // 后面就可以通过 this.state 来获得这个对象
    getInitialState: function() {
        return {
            key1: data1,
            key2: data2,
            ...
        };
    },
    // 这里一般做一些和界面显示无关的初始化操作
    componentWillMount: function() {
    },
    // 这里一般做加载数据的操作
    componentDidMount: function() {
    },
    // 这是最重要的函数,用来绘制界面,
    // 所有的自定义组件,这个函数是必须提供的
    render: function() {
        return(
            <View>
                ...
            </View>
        );
    },
});

一个自定义组件基本上就是上面那样定义了。只有 render 函数是必须的,其他都是可选的。

3. 组件的数据

绘制界面部分,一般情况下会根据组件的状态 state 来绘制动态页面,例如下面一个最简单的例子:

render: function() {
    return(
        <Text>{this.state.key1}</Text>
    );
}

这里就是直接把状态中的 key1 的值用 Text 组件直接显示出来。

另外,React 组件中最重要的一个概念就是 state — 组件的状态。除了前面的使用 getInitialState 方法来设置初始化状态外。在界面逻辑处理或者事件交互的过程中,可以调用 this.setState(...) 方法来修改组件的状态值。

如果在代码中直接修改 state,React 就会把旧状态和新状态做一个 diff,找到变化的部分,然后对应找到和这个变化的值关联的界面部分,请求重新绘制这个部分。例如刚才的例子中,如果调用:

this.setState({key1: 'Hello world!'});

界面上的 Text 内容马上就会显示出 Hello world!

组件中还有一种数据:属性(Property),这种数据可以通过 this.props 来直接获取,例如非常常见的

<View style={{flex: 1}}>

这里的 style 就是 View 这个组件的一个属性。

那么属性(props)和状态(state)两种数据有什么区别呢?一般 属性 表示静态的数据,组件创建后,就基本不变的内容,状态 是动态数据。

4. React Native 布局

关于 React Native 的布局,实用的是 FlexBox 实现,类似网页的 CSS 布局方法,具体可以参考官方推荐的 A Complete Guide to Flexbox 和官方文档 Flexbox。关于布局说起原理比较简单,但是要很灵活的写出你想要的样式,还是需要慢慢积累经验。

另外,值得一提的是,React Native 中的样式长度单位,是逻辑单位,概念和 Android 中的 dp 一样。

以上就是 React Native 的基本逻辑,有了这些概念,我们就可以开始写 APP 了。

APP 开发实践

我们要实现的知乎日报的 APP 的主页面是一个文章列表,左边可以滑动出来抽屉,账号信息和显示主题列表。选择主题列表,可以在列表页更新对应主题的文章列表。点击文章列表进入文章详情。还有评论,点赞,登录等功能初期并不计划做。

1. 抽屉的实现

庆幸的是,官方提供了 DrawerLayoutAndroid 组件,这个组件其实就是对 Android 中的 DrawerLayout 的封装。可以参考官方文档,使用过 Native 版本的 DrawerLayout 话,很容易上手这个组件。主要代码如下:

render: function() {
  ...
  return (
    <DrawerLayoutAndroid
      ref={(drawer) => { this.drawer = drawer; }}
      drawerWidth={Dimensions.get('window').width - DRAWER_WIDTH_LEFT}
      keyboardDismissMode="on-drag"
      drawerPosition={DrawerLayoutAndroid.positions.Left}
      renderNavigationView={this._renderNavigationView}>
      <View style={styles.container}>
         ...
        {content}
      </View>
    </DrawerLayoutAndroid>
  );
}

其中 renderNavigationView 属性,表示抽屉里面显示的内容。本项目的实现,可以参考:ListScreen.js

2. 主页文章列表

文章列表在 Android 可以用 ListView 实现,React Native 也很贴心提供了对应的组件ListView。实用方法和 Android 原生的也类似,需要提供一个数据源 dataSource 和一个基本的绘制每行界面的函数。借用官方的一个代码片段:

getInitialState: function() {
  var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
  return {
    dataSource: ds.cloneWithRows(['row 1', 'row 2']),
  };
},

render: function() {
  return (
    <ListView
      dataSource={this.state.dataSource}
      renderRow={(rowData) => <Text>{rowData}</Text>}
    />
  );
},

这是一个最简的 ListView 使用的例子。其实,React Native 提供的 ListView 比原生还要强大一些,提供了列表的 Section 的支持,列表可以分节,可以显示每节的头部,这个和 iOS 的 UITableView 类似。

因为知乎日报的文章列表是按照日期分 Section 的。具体的使用方法在官方的例子UIExplorer 中有例子。问项目中可以参考这个文件: ListScreen.js

3. 详情页的实现

知乎日报的文章详情页是使用一个 WebView 显示内容的。遗憾的是,React Native 官方在 Android 上并没有提供 WebView 的支持。好在 React Native 很容易集成原生的组件:Native UI Components。我就按照官方文档,导出一个 React 的 WebView 组件。Java 端的代码如下:

public class ReactWebViewManager extends SimpleViewManager<WebView> {

    public static final String REACT_CLASS = "RCTWebView";

    @UIProp(UIProp.Type.STRING)
    public static final String PROP_URL = "url";

    @UIProp(UIProp.Type.STRING)
    public static final String PROP_HTML = "html";

    @UIProp(UIProp.Type.STRING)
    public static final String PROP_CSS = "css";

    @Override
    public String getName() {
        return REACT_CLASS;
    }

    @Override
    protected WebView createViewInstance(ThemedReactContext reactContext) {
        return new WebView(reactContext);
    }

    @Override
    public void updateView(final WebView webView, CatalystStylesDiffMap props) {
        super.updateView(webView, props);
        if (props.hasKey(PROP_URL)) {
            webView.loadUrl(props.getString(PROP_URL));
        }

        if (props.hasKey(PROP_HTML)) {
            String html = props.getString(PROP_HTML);
            if (props.hasKey(PROP_CSS)) {
                String css = props.getString(PROP_CSS);
                html = "<link rel=\"stylesheet\" type=\"text/css\" href=\"" + css + "\" />" + html;
            }
            webView.loadData(html, "text/html; charset=utf-8", "UTF-8");
        }

    }
}

这里我导出了一个简单的 WebView,并暴露了 url, html, css 三个属性。url 表示网页要显示的网页地址,html 表示要加载的 HTML 字符串, css 表示网页样式链接。还要注册这个 ReactWebViewManagerReactInstanceManager 中。具体代码可以看MyReactPackage.javaMainActivity.java

在 JS 端,需要做对应的封装:

class ObservableWebView extends React.Component {
  ...

  render() {
    return <RCTWebView {...this.props} onChange={this._onChange} />;
  }
}

ObservableWebView.propTypes = {
  url: PropTypes.string,
  html: PropTypes.string,
  css: PropTypes.string,
  onScrollChange: PropTypes.func,
};

var RCTWebView = requireNativeComponent('RCTWebView', ObservableWebView, {
  nativeOnly: {onChange: true}
});

module.exports = ObservableWebView;

然后就可以在 React 中使用了,如下:

var MyWebView = require('./WebView');

render: function() {
    return (
      <View style={styles.container}>
        <MyWebView
          style={styles.content}
          html={this.state.detail.body}
          css={this.state.detail.css[0]}/>
      </View>
    );
}

这样就能直接显示了网页内容,挺出乎我意料的简单。

还有一个细节,官方客户端,随着 WebView 的滑动,头部的 Image 也跟着往上收起来。这里我们就要监听 WebView 的滑动事件,然后来设置头部的 Image 的跟随移动。还好,官方文档也提供了一个可以方便从 Native 往 React 传递事件的方法:Events。跟着文档来,实现了一个 ObservableWebView,继承于原生的 WebView,同时把滑动事件上报给 React:

// ObservableWebView.java
public class ObservableWebView extends WebView {
    ...
    @Override
    protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt)
    {
        super.onScrollChanged(l, t, oldl, oldt);

        WritableMap event = Arguments.createMap();
        event.putInt("ScrollX", l);
        event.putInt("ScrollY", t);
        ReactContext reactContext = (ReactContext)getContext();
        reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
                getId(), "topChange", event);
    }
}

这里在 onScrollChanged() 回调中,就是往 React 中报 topChange 事件。事件中包含 ScrollXScrollY 两个值。这里的 topChange 被映射到了 JS 的 onChange 事件。在 React 层就能这样用了: <MyWebView onChange={onChangeCallback}/>,这里的 onChangeCallback 是一个自定义的回调函数。WebView 滑动的时候,就会回调到这个函数中来。为了实用方便,这里还可以做一些封装,把 topChange 封装为我们关心的滑动事件onScrollChange

class ObservableWebView extends React.Component {
  constructor() {
    super();
    this._onChange = this._onChange.bind(this);
  }

  _onChange(event: Event) {
    if (!this.props.onScrollChange) {
      return;
    }
    this.props.onScrollChange(event.nativeEvent.ScrollY);
  }

  render() {
    return <RCTWebView {...this.props} onChange={this._onChange} />;
  }
}

详情可以参考:WebView.js

这时,我们就可以在 React 组件中的 onScrollChange 事件回调中实现滑动详情页的头部图片的效果:

onWebViewScroll: function(event) {
    // 这里移动头部的 Image
},
render: function() {
    return (
        <View style={styles.container}>
            <MyWebView
              ...
              onScrollChange={this.onWebViewScroll}/>
            <Image
              ref={REF_HEADER}
              source={{uri: this.state.detail.image}}
              style={styles.headerImage} />
            {toolbar}
        </View>
    );
},

这里的写起来也很简单。关键看一下 onWebViewScroll 函数的实现。最简单的实现方法就是,通过 ScrollY 来设置组件的 state,来让 React 自动触发重绘。因为事件上报非常频繁,就会触发大量的重绘,会带来严重的性能问题。

React Native 提供了 Direct Manipulation,也就是直接操作组件,这种方式不会触发重绘,效率会高很多。

onWebViewScroll: function(event) {
      // 像素转为 React 中的大小单元
    var scrollY = -event / PIXELRATIO;
    var nativeProps = precomputeStyle({transform: [{translateY: scrollY}]});
    // 直接操作组件的属性
    this.refs[REF_HEADER].setNativeProps(nativeProps);
},

到这里,实现这个 React Native 版的知乎日报客户端所涉及的技术点,基本都讲完了。还有很多细节请参考源码:ZhiHuDaily-React-Native,欢迎一起交流,和发 pull request 来一起完善这个项目。

总结

这篇文章几百字就写完了,看起来实现这个客户端并不复杂。其实,这里有远超过我想象的坑,后面我应该还会写一篇文章,来总结这个项目中遇到的坑。总体来说,React Native for Android 作为初期的版本,实现一个简单 APP 已经可行。但是它并不完善,如果想用在实际项目中,还需要慎重考量。

最后,大家可以关注这个项目:ZhiHuDaily-React-Native。希望能对开始关注 React Native 的同学有些帮助。


10 best IOT Hardware platforms

$
0
0

10 best IOT Hardware platforms

Share on Facebook13Share on Google+93Tweet about this on Twitter14Share on Reddit0Share on LinkedIn1Share on StumbleUpon42Pin on Pinterest1

IOT is growing rapidly and we are not far from days where our machines can interact with each other and act accordingly. In fact we will be left behind if we don’t adapt or learn this amazing technology. Here is a list of 10 best IOT hardware platforms which will help us to learn and prototype IOT devices and stuffs.

This list was compiled after seeking experts opinions, conducting polls, forum discussions and much more. Therefore it reflects the choice of many Embedded Programmers and designers. I believe this list will help to choose the perfect platform for  you.

1) Arduino Yun:

arduino-yun-development-board

Arduino Yun is a hybrid board which has inbuilt Ethernet and Wi-Fi connectivity features. This board is powered by ATmega32u4 which handles USB communication whereas the powerful Atheros AR9331 which handles the Wifi and Ethernet interfaces and comes with a Linux distribution based on OpenWrt. There is no need to add external shileds and interfaces for providing internet connectivity. Also you will get tons of technical support from its huge community. This makes Arduino Yun a great platform for developing IOT projects.

Buy Arduino Yun from Amazon here.

2)Raspberry Pi:

raspberry-pi-development-board

Raspberry Pi is a credit card sized computing platform which runs on linux platform. This board features USB ports for keyboard and mouse, a HDMI port for display and an Ethernet port for wired internet connectivity. However for wireless connectivity we need to go for Wifi adapters which we can get it from the market without any trouble. The vast community makes it perfect to develop IOT projects since we get plenty of hands when we stumble.

Buy Raspberry Pi 2 from Amazon

3)ESP8266:

esp8266-wifi-chip-iot

ESP8266 is a Wi-Fi module that is capable of providing internet connectivity to any microcontroller through UART communication. Also it comes with an integrated TCP/IP protocol stack. Each of these module comes pre programmed with AT commands making it easy to plug and play for IOT projects. This module also can also be used for specific application devices and sensors by using its GPIO pins.

4)Beaglebone Black:

beaglebone-black-development-board

Beaglebone Black is a pretty famous low-cost development platform built around ARM Cortex A8 processor. It runs on Linux environment just like the Raspberry Pi. This board has in-built Ethernet Connectivity feature along with HDMI port to connect a monitor to work on. The robust community of Beaglebone makes it outstanding and viable solution to learn and built IOT projects.

Buy Beaglebone Black Rev C from Amazon.

5) Particle.io (Photon and Electron) :

particle-io-photon

Particle.io (formerly known as Spark Core) Photon and Electron is a Wi-Fi enabled IOT hardware platform. It was built using powerful STM32 ARM Cortex M3 and Broadcom Wi-Fi chip . The striking feature of this Particle products is a website cloud platform that allows user to send and receive data seamlessly from anywhere rather than only accessing data from your local network.

6) Intel Edison:

intel-edison-development-board

Intel Edison is a tiny development platform  featuring a Intel Atom CPU and 32 bit Intel Quark microcontroller. This tiny board carries all Wi-Fi and bluetooth modules for connectivity and thus requires no external modules to do so. Also it carries other striking features such as UART, SPI, I2C, I2S, GPIO and SD card support.

7) Arduino + Shields:

arduino-ethernet-shield

Arduino is pretty familiar in the world of prototyping however only some boards have inbuilt internet connectivity. Meanwhile while other Arduino boards can be used with a external shields to provide the connectivity. You can use Ethernet shield for wired connections and Wi-Fi shield for Wireless connection to the internet. Arduino is significant tool in IOT development because of its robust community.

8) Netduino:

netduino-3-ethernet-development-boardNetduino is an open source electronics prototyping platform build around STMicro STM32F4 controller and runs in .NET Micro Framework. Special versions of this Netduino Ethernet and Wi-Fi certainly gives an edge for IOT developers and enthusiasts. Ethernet board equipped with inbuilt Ethernet connectivity and Wi-Fi connectivity for the Wi-Fi board. Other features such as UART, I2C, SPI and SD card connectivity adds flavor to it.

9) Flutter:

flutter-development-board

 

Flutter is a basic radio board powered by SMART SAM3S Cortex-M3 processor provides a range of about half a mile. This board lets users to develop mesh networking protocols and connect devices with least power expense. It is also equipped with ATSHA204 crypto engine to keep the data transmission safe.

10) Tessel 2:

tessel-2-development-board

Tessel 2 is an affordable yet robust IOT hardware platform powered by Atmel SMART SAMD21 Cortex M0+ processor  to control IO and Mediatek MT7260n Wi-Fi Router SOC to take care of the connectivity. The board is equipped with built-in WI-Fi , Ethernet port, USB port and runs real Node.js/io.js.

And that’s the end of 10 best IOT hardware platforms to learn and prototype devices. I hope this list might have given some idea about the platforms. However do remember there are plenty of hardware platforms available in the market and this article only listed out handful, famous and most preferred by users. So do make research on it and make sure the platform meets your needs. All the best and happy building.


DIY Sous vide cooker with Meteor App

$
0
0

Final Project

http://fab.cba.mit.edu/classes/863.14/people/matthew_arbesfeld/2014/12/14/final-project/

For my final project I built a sous-vide immersion cooker:

 

Sous-vide is a method for cooking food in a temperature-controlled water environment for longer than normal cooking times, at an accurately regulated temperature. Sous-vide cookers are often used in high-end restaurants. In the past few years, however, they have become more popular in household kitchens.

An average sous-vide cooker costs $2000, with low-end cookers going for around $300. I wanted to build my own cheaper version of the device. I also wanted to be able to control it via Bluetooth, so that I could leave the device in my room and control it from anywhere on my floor.

Just want to see the food it can make? Click here

Electronics

The electronics for the cooker are fairly simple. We really are dealing with three components:

  • A waterproof temperature sensor: DS18B20
  • A switched AC current via a solid-state relay: SSR-25da
  • Bluetooth for serial input / output: BLE Mini

I got a chance to play around with the temperature sensor and BLE mini device in week 11. I also got the solid-state relay working in week 10. This week, I brought all of the components together on a single board.

Reading Temperature

Step 1 is to read the temperature of the water. I found a handy device which could do exactly this, a DS18B20:

A ‘one wire’ waterproof temperature sensor.
A 'one wire' waterproof temperature sensor.

This is known as a “one-wire device,” because data from the sensor is transferred over a single wire. We also connect a VCC and GND wire, so there are three wires in total. In software, there is a OneWire Arduino librarywhich lets you create a OneWire bus for data transfer. Dallas Temperature created their own library on top of the OneWire library which provides intuitive commands for reading temperature:

#include <OneWire.h>
#include <DallasTemperature.h>

// Where the temperature sensor probe is connected.
#define ONE_WIRE_BUS 14

// Setup a OneWire instance to communicate with any devices.
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature(&oneWire);

void setup() {
  // Start up the library.
  sensors.begin();
}

void loop() {
  sensors.requestTemperatures();
  float tempC = sensors.getTempCByIndex(0);
}

Switching AC Current

I used these guys to heat water. They’re AC powered, so we need a way to turn them on and off via a signal from our microcontroller. The most common way to do this is via a solid state relay.

 

The green wires are connected to a pinout and GND, and the white wire intersects a link to the heaters. When the pin is turned on, current from the wall socket can flow to the heaters.

Bluetooth

The final piece of the puzzle is Bluetooth. I used the BLE Mini device from RedBearLabs. The device is super simple to setup. Since I was using an ATMega which has hardware serial, I simply connected RX/TX to the microcontroller and powered the board. It worked on the first try.

Bluetooth + temperature sensing in action:

Power

I needed an AC -> 5V power adapter. The only thing I had on hand was an iPhone charger, but any ~1A power adapter would do the trick.

Board Assembly

Here is the schematic for my board:

 

and the layout:

 

Some points about this design:

  • An ATMega328 was required because the libraries are larger than 8kb.
  • 2×2 headers provide an interface for input/output devices to the microcontroller
  • The board is powered via 5V USB.
  • I drilled holes in the board (shown in green) to serve as mounting points.

The only hard part about soldering the board are the small leads on the ATMega.

Tape served as a lever for positioning the chip.
Tape served as a lever for positioning the chip.
The final board, with all soldered components.
The final board, with all soldered components.

Hardware

Since I will be running 120V AC through my circuit, I needed to build an enclosure to house the various components of the device. No one likes electrocution!

Design

My tool of choice for the design was SolidWorks. I wanted very precise measurements, because I would be mounting various components to the enclosure. Also, I wanted to be able to define the model parametrically, to allow me to quickly change the design if needed.

The final SolidWorks model.
The final SolidWorks model.
Equations defining the enclosure.
Equations defining the enclosure.

Download the SolidWorks file.

Printing

I used the MakerBot Replication 2 with PLA plastic. MakerBot has proprietary software for printing .obj and .stl files.

Printing the top of the case in MakerWare
Printing the top of the case in MakerWare
 
Printing in progress.
Printing in progress.

I was quite pleased with how the parts came out:

The top half of the enclosure. 10 hour print, 0.33 pounds of PLA.
The top half of the enclosure. 10 hour print, 0.33 pounds of PLA.
The bottom half of the enclosure, with mounted power sockets. 3 hour print, 0.25 pounds of PLA.
The bottom half of the enclosure, with mounted power sockets. 3 hour print, 0.25 pounds of PLA.

A few interesting points about my enclosure:

  • I used a friction-fit sliding mechanism to attach the two parts of the case. Clearance was only 0.01”, so I had to do quite a bit of sanding to get the part to fit. Make sure to account for 3d printing artifacts when calculating your tolerances.
  • For AC connectors, I used this female outlet and this male socket from Amazon. I copied the “mounting size” directly from Amazon, but really should have left some clearance to let the parts slide in more easily.
  • Screw mounting works great with PLA plastic. I left ~0.1” holes and hand drilled 6×3/4” screws into the plastic.
  • I also built a small power-strip. We power a circulation pump whenever the sous-vide is turned on.
  • In order to make the device as general as possible, you can plug in any device which is switched on by the relay. This lets you connect devices other than heaters to the unit. For example, we could control a refrigeration unit with the same device.

Assembly

Once my 3d prints finished, it was time to assemble everything together!

This was my first time working with AC power, but I learned a few tricks:

  • 16 or 18 gauge wire must be used to carry the high AC current.
  • Wire nuts work great for attaching multiple wires together.
  • Don’t forget to solder wires onto the power leads.
  • There is nothing wrong with copious amounts of electrical tape.
Wiring the front face of the enclosure with 16 gauge wire.
Wiring the front face of the enclosure with 16 gauge wire.
The solid state relay is mounted on a heatsink which is attached to the enclosure via screws.
The solid state relay is mounted on a heatsink which is attached to the enclosure via screws.
These things work great for connecting multiple wires together.
These things work great for connecting multiple wires together.
Screwing the PCB into the mount holes.
Screwing the PCB into the mount holes.
Taken just before closing the enclosure. Everything is tested and working!
Taken just before closing the enclosure. Everything is tested and working!
Sliding the top into place.
Sliding the top into place.
Everything sealed tightly inside. Ready to make some food!
Everything sealed tightly inside. Ready to make some food!

Woo! That was a lot of work.

My post on Hacker News garnered a lot of feedback on the AC component of my design. There were safety issues in my original design which should have been addressed. Thank you to cnvogel and mikeytown2.

  • I should have used crimped terminal connectors to connect the wire to the inlet sockets.
  • Terminal blocks are safer than screw caps for connecting cables.
  • I could have 3d printed a clip that goes over the terminals on the relay.
  • Always design enclosures with a physical barrier between the “high voltage” side and the “low voltage” side.
  • Running the AC through a device like this or this would have made it much safer, especially since we are dealing with water.

Application Programming

I go into detail about the SousVide controller application in Week 11. In essence, the app is a cross-platform mobile app that lets you control the temperature and duration of your sous-vide recipes. Some features include:

  • Signing in (via Google) to save recipes.
  • Notifications when the recipe duration has elapsed
  • Preheating the sous-vide, and cooking when ready.
  • Monitoring temperature and on/off state of the sous-vide.
A screenshot of the app, when cooking food. The blue text indicates that the heaters are switched off (because the current temperature is slightly higher than the target).
A screenshot of the app, when cooking food. The blue text indicates that the heaters are switched off (because the current temperature is slightly higher than the target).

All of the code is available on my GitHub.

Cost

Parts:

Total cost: ~$100

Overall, this project was much cheaper than buying a conventional sous-vide. Moreover, this device can control any arbitrary AC current based on temperature via Bluetooth. For example, we could use the same device to smoke meats or refrigerate beer.

Results

Finally, it’s time for the food porn! A sous-vide is only as good as the food it makes:

Eggs

My first test was cooking eggs at 76C for 45 minutes:

Soft-boiling eggs at 76C.
Soft-boiling eggs at 76C.
Delicious! The yolk tasted like butter!
Delicious! The yolk tasted like butter!

Hamburger

I cooked a burger at 57C and then seared on the grill for a great medium-rare:

Using a cup to hold the burger submerged in the liquid. Yea, the food looks kinda gross as it is being cooked.
Using a cup to hold the burger submerged in the liquid. Yea, the food looks kinda gross as it is being cooked.
 
I’m enjoying the burger.
I'm enjoying the burger.

Steak

Steak is the quintessential sous-vide item. I cooked this boneless ribeye at 56C for 90 minutes.

The steak après sous-vide.
The steak après sous-vide.
Searing the food after sous-vide seals in the juices and makes it look more appetizing.
Searing the food after sous-vide seals in the juices and makes it look more appetizing.
Medium-rare throughout the whole steak. This is really hard to achieve with conventional cooking techniques.
Medium-rare throughout the whole steak. This is really hard to achieve with conventional cooking techniques.
Steak and sweet potato medallions — the perfect way to celebrate the end of a semester!
Steak and sweet potato medallions -- the perfect way to celebrate the end of a semester!

Android RecyclerView Example

$
0
0

Android RecyclerView Example

1. What is RecyclerView?

Google’s upcoming operating system named Android L looks very promising. It is highly focused on rich user experience and what they called it as material design. In this example we will take a look at the new UI widget called RecyclerView.

RecyclerView is more advanced and flexible and efficient version of ListView. RecyclerView ViewGroup is an container for larger data set of views that can be recycled and scrolled very efficiently. RecyclerView can be used for larger datasets to be rendered on the UI like a list. RecyclerView provides maximum flexibility to design different kind of views

2. RecyclerView Example

The tutorial, download the feed data from server, parse the JSON feed response and display the items on list. This example using both RecyclerView and CardView for creating the UI as shown in the following video.

To accomplish this result as shown in the above video, we need to follow the following steps:

  1. Create a new Android application in Android Studio IDE and add the support library dependency.
  2. Declare an layout for your activity and add a RecyclerView and ProgressBar widget
  3. Create an activity class to initiate data download, initialize the adapter and display data on RecyclerView
  4. Create RecyclerView row layout. Here we will use the CardView widget.
  5. Create an custom adapter that will be used for RecyclerView
  6. Implementing RecyclerView click event handling

2.1. Adding Support Library

Android SDK doesn’t includes the RecyclerView class, and hence for using RecyclerView in your project you first need to add the recycler view support library to your project. Android Studio users can add the following graddle dependency to project build.graddle file.

dependencies {
       compile 'com.android.support:recyclerview-v7:+'
       compile 'com.android.support:cardview-v7:21.0.+'
       compile project(':picasso-2.3.4')
}

Notice that in the above dependency declaration, I have added the RecyclerView and CardView support library, and the Picasso.jar. Before this, you need to add Picasso jar module by going to your Android Studio Project properties.

2.2. Adding Internet Permission

You might be aware that, Android application must declare all the permissions that are required for application. As we need to download the data form server, we need to add the INTERNET permission. Add the following line toAndroidManifest.xml file.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.javatechig.app">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
       .....
    </application>
</manifest>

2.3. Declaring Activity Layout

Our first step towards this example is to declare the activity layout. Here in this example, we will add a RecyclerView and ProgressBar inside aRelativeLayout. The progress bar will be shown to user while the data is being downloaded. Add the following code snippets tolayout/activity_feed_list.xml file.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="@dimen/activity_vertical_margin">

    <view
        android:id="@+id/recycler_view"
        class="android.support.v7.widget.RecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true" />

    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" />
</RelativeLayout>

2.4. Activity Using RecyclerView

RecyclerView is a ViewGroup similar to ListView or GridView. A ViewGroup is an UI widget that is used to render collection of data. In this example, we are trying to download the latest feeds from this site and display it on RecyclerView.  The focus of this tutorial is narrow down to RecyclerView, hence it doesn’t include any explanation for download and parse data from server. For learning how to download data from server, you may read Android Networking Tutorial.

As the data is downloaded, inside onPostExecute() we are initializing the adapter and setting adapter to RecyclerView instance by just calling setAdapter()method.

package com.javatechig.app;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class FeedListActivity extends AppCompatActivity {
    private static final String TAG = "RecyclerViewExample";
    private List<FeedItem> feedsList;
    private RecyclerView mRecyclerView;
    private MyRecyclerAdapter adapter;
    private ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_feeds_list);

        // Initialize recycler view
        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        progressBar = (ProgressBar) findViewById(R.id.progress_bar);
        progressBar.setVisibility(View.VISIBLE);

        // Downloading data from below url
        final String url = "http://javatechig.com/?json=get_recent_posts&count=45";
        new AsyncHttpTask().execute(url);
    }

    public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {

        @Override
        protected void onPreExecute() {
            setProgressBarIndeterminateVisibility(true);
        }

        @Override
        protected Integer doInBackground(String... params) {
            Integer result = 0;
            HttpURLConnection urlConnection;
            try {
                URL url = new URL(params[0]);
                urlConnection = (HttpURLConnection) url.openConnection();
                int statusCode = urlConnection.getResponseCode();

                // 200 represents HTTP OK
                if (statusCode == 200) {
                    BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = r.readLine()) != null) {
                        response.append(line);
                    }
                    parseResult(response.toString());
                    result = 1; // Successful
                } else {
                    result = 0; //"Failed to fetch data!";
                }
            } catch (Exception e) {
                Log.d(TAG, e.getLocalizedMessage());
            }
            return result; //"Failed to fetch data!";
        }

        @Override
        protected void onPostExecute(Integer result) {
            // Download complete. Let us update UI
            progressBar.setVisibility(View.GONE);

            if (result == 1) {
                adapter = new MyRecyclerAdapter(FeedListActivity.this, feedsList);
                mRecyclerView.setAdapter(adapter);
            } else {
                Toast.makeText(FeedListActivity.this, "Failed to fetch data!", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void parseResult(String result) {
        try {
            JSONObject response = new JSONObject(result);
            JSONArray posts = response.optJSONArray("posts");
            feedsList = new ArrayList<>();

            for (int i = 0; i < posts.length(); i++) {
                JSONObject post = posts.optJSONObject(i);
                FeedItem item = new FeedItem();
                item.setTitle(post.optString("title"));
                item.setThumbnail(post.optString("thumbnail"));

                feedsList.add(item);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

Notice that in the above code snippet, we are using the FeedItem POJO class to parse the data from server. Create a new file named FeedItem.java class in your project source folder and add the following snippets.

package com.javatechig.recyclerview;

public class FeedItem {
    private String title;
    private String thumbnail;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getThumbnail() {
        return thumbnail;
    }

    public void setThumbnail(String thumbnail) {
        this.thumbnail = thumbnail;
    }
}

2.5. Creating RecyclerView Adapter

Android RecyclerView includes special kind of adapter which works pretty much same as traditional Android adapters but with additional functionalities. The additional functionalities includes;

  • It adds two new methods like onCreateViewHolder() andonBindViewHolder() to organize the code. You must override these two methods for inflate the view and to bind data to the view
  • Implements a ViewHolder by default. ConceptuallyRecyclerView.ViewHolder works same as the ViewHolder design pattern which we have been using with other Adapters
  • Takes care of the overhead of recycling and gives better performance and scrolling
package com.javatechig.app;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.squareup.picasso.Picasso;
import java.util.List;

public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.CustomViewHolder> {
    private List<FeedItem> feedItemList;
    private Context mContext;

    public MyRecyclerAdapter(Context context, List<FeedItem> feedItemList) {
        this.feedItemList = feedItemList;
        this.mContext = context;
    }

    @Override
    public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, null);

        CustomViewHolder viewHolder = new CustomViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(CustomViewHolder customViewHolder, int i) {
        FeedItem feedItem = feedItemList.get(i);

        //Download image using picasso library
        Picasso.with(mContext).load(feedItem.getThumbnail())
                .error(R.drawable.placeholder)
                .placeholder(R.drawable.placeholder)
                .into(customViewHolder.imageView);

        //Setting text view title
        customViewHolder.textView.setText(Html.fromHtml(feedItem.getTitle()));
    }

    @Override
    public int getItemCount() {
        return (null != feedItemList ? feedItemList.size() : 0);
    }
}

2.6. RecyclerView Row Layout

The above code mentions about another new layout list_row.xml. This is defies the layout for RecyclerView item.  Here in this example, we are using the CardView as parent layout and CardView hosts a RelativeLayout with an ImageView and TextView.

Click here to learn more about Android CardView.

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:cardview="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="80dp"
    android:layout_margin="8dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="80dp">

        <ImageView
            android:id="@+id/thumbnail"
            android:layout_width="100dp"
            android:layout_height="80dp"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:scaleType="centerCrop"
            android:src="@drawable/placeholder" />

        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@+id/thumbnail"
            android:maxLines="3"
            android:padding="8dp"
            android:text="dafdafda"
            android:textColor="#222"
            android:textSize="15dp" />

    </RelativeLayout>
</android.support.v7.widget.CardView>

2.6. Implementing ViewHolder Pattern

Now let us create our ViewHolder class. The ViewHolder contains the reference to the each of the ui widget on the row. We have defined this class as a private class inside MyRecyclerAdapter.

public class CustomViewHolder extends RecyclerView.ViewHolder {
        protected ImageView imageView;
        protected TextView textView;

        public CustomViewHolder(View view) {
            super(view);
            this.imageView = (ImageView) view.findViewById(R.id.thumbnail);
            this.textView = (TextView) view.findViewById(R.id.title);
        }
    }

3. Handle RecyclerView Click Event

Handling click event on RecyclerView is not as sweet as handling click listener in ListView or GridView. Android RecyclerView doesn’t provide any built in listeners or handy way of handling click events.

However we can use workaround to handle click event explicitly by adding the following code in onBindViewHolder() method.

//Handle click event on both title and image click
customViewHolder.textView.setOnClickListener(clickListener);
customViewHolder.imageView.setOnClickListener(clickListener);

customViewHolder.textView.setTag(customViewHolder);
customViewHolder.imageView.setTag(customViewHolder);

Add declare the clickListener variable as follows

View.OnClickListener clickListener = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        CustomViewHolder holder = (CustomViewHolder) view.getTag();
        int position = holder.getPosition();

        FeedItem feedItem = feedItemList.get(position);
        Toast.makeText(mContext, feedItem.getTitle(), Toast.LENGTH_SHORT).show();
    }
};

4. Download Source Code

Download from GitHub.


Eagle: Extract a symbol from a project to a library

$
0
0

Eagle: Extract a symbol from a project to a library

Eagle – a widespread PCB design tool – comes with a huge amount of libraries but sometimes it is missing the exact device you need for your project. A common way to add a new device to your libraries is to copy an existent but similar one and to adapt it to your needs.

Another more comfortable solution is – assuming you downloaded an existent eagle project from the internet – to generate a complete library with all the devices used in the schematic or board file of that project.

It’s done amazing easy with a few clicks only. In your menu toolbar there’s the ULP tool. ULP stands for User Language Program which is the language used to write scripts to add new functionality to eagle. These scripts can be seen as a kind of plugins such as there are add-ons in firefox to give it new abilities.

After clicking on the ULP tool you have to choose the exp-project-lbr.ulp ULP script.

Update (April 11th, 2013):

As of version 6.4 the export of schematic and/or board libraries has been integrated into the EAGLE GUI, available in the File menu under Export/Libraries while the new ULP exp-lbrs.ulp is replacing the existing exp-project-lbr.ulp.

The new script hasn’t been tested yet and thus the rest of this article is still referencing the old ULP. Please leave a comment if this howto cannot be applied any longer.

The script will ask you for some options but chances are that you leave them unchanged. Just click on the Collect data and Create library afterwards.

Optionally also the mechanical packages can be generated. Make your choice.

The generation can take a while now depending on the schematic and board complexity. The ULP script will finally create a file with the file name of your schematic but uses lbr as the file extension then.

You should have got now what you were looking for.


A development board for the STM32F042 TSSOP package

$
0
0

It’s been a while since I posted a new article, a delay at least partly due to me herniating a disc in my neck which left me completely unable to look downwards for any length of time and as you’ll know all too well you can’t work on circuit boards without peering down at them. Look after your neck and back folks, and I mean that seriously.

Well I’m back now and I’ve got a lot of ideas for articles spinning around in my head that will hopefully come to fruition over the next few months. First off the block is this one in which I’m going to present a simple development board for the STM32F042 in the easy(ish) to work with TSSOP20 package.


STM32F042 TSSOP20 0.65mm pitch package

This project came about because I’m using the STM32F042F6P6 (32Kb flash, 6Kb SRAM) in another project where I’m creating a USB device and the first thing I did is try to obtain a development board for it. I was hopeful that ST would have created one of their ‘discovery’ boards but no, there was only a ‘nucleo’ board available and that had one of the QFP packages on it.


The F042 nucleo board

The nucleo board would have probably been sufficient for my needs but I do prefer to work on the actual device that’s going to be used in the real project and I had a few ideas for features that I’d include that I wish would be included in other development boards but never seem to be.

Development board features

  • USB. The 042 series supports USB and although 32Kb is not a lot of space to include a USB driver and your application logic it does make sense to hook up those USB data lines and thereby enable USB device development.
  • Switching regulator. All the development boards that I’ve seen seem to use a low dropout regulator (LDO) to supply power to the MCU which means that they’re unable to supply much current to any peripherals that you’re prototyping. The discovery boards warn you not to draw more than 100mA and many of the 3rd party boards use one of the 1117 regulators which, with up to a 1A limit, look great on paper but the universally chosen SOT-223 package will burn up in smoke long before you get anywhere near that figure.
  • VDDA control.The discovery boards allow you to supply VDDA externally if required. I’d like to keep this ability.
  • Onboard 8MHz crystal. All the F0 series can be clocked from the internal high speed internal (HSI) 8MHz oscillator with an option to use an external 8Mhz crystal. I’ll include such a crystal on my board.
  • Onboard NPN transistor. I often need to use an NPN transistor as a low-side switch to control a load either requires too much current to power from a GPIO or is running from a different voltage level (e.g. 5V). I’ll include a simple transistor on this board configured ready to function as a switch.
  • A LED. Because, well, you know, blinky.

Schematic



Click for a PDF

The schematic is rather modular so let’s take a look at each section in detail.

The power supply

The 3.3V voltage for the board is supplied by a Texas Instruments LMR10515 adjustable switching buck (step-down) regulator. I’ve used this regulator a few times before and have found it to be a solid and reliable device that doesn’t require many external components and only costs about 50 pence from Farnell.

This regulator is capable of supplying up to 1.5A with an efficiency level of over 90% throughout most of its range. The input will be the 5V VBUS line from the USB plug after I’ve sanitised it to remove the gremlins that lurk therein.

It’s this efficiency level that allows switching regulators to deliver their peak current rating without burning up in a puff of smoke. The output inductor and schottky diode must both be chosen to match the desired peak current from the regulator. For the inductor I’ve chosen the Murata LQH44PN3R3MP0L (2.1A maximum current) and for the schottky I’m using an ST Micro STPS0520Z (0.5A maximum current).

In practice this means that my development board is limited to 500mA but you can use any schottky that will fit the SOD-123 footprint if you need a higher current supply up to the 1.5A maximum that the regulator can deliver.

The MCU

The MCU power and reset scheme is wired up according to ST’s recommendations. VDD gets a pair of 100nF and 4.7µF capacitors and VDDA gets a 10nF and 1µF pair. P3, a 4 pin header, receives a jumper across pins 1 and 2 to connect VDDA to the onboard 3.3V supply or the jumper can be removed to allow an external VDDA to be connected to pin 3.

C4 decouples the active-low reset pin to prevent any spurious resets from ruining your day. There’s no need for a pull-up to VDD because ST supply one internally.

The crystal is connected to the MCU via a pair of 0R ‘resistor’ bridges that can be removed if you’ve fitted a crystal but want to use the PF0 and PF1 pins as GPIO without fear of interference from the crystal itself.

If you’re considering USB device development and you’ve done this before then you may think that you’re going to need the external crystal to generate the accurate 48MHz clock required by USB to stay in sync with the host, but this is not the case. ST supply an internal ‘HSI48′ 48MHz clock specifically for use with the USB peripheral and with a bit of software configuration you can not only clock the MCU core from it but you can also constantly trim its accuracy from the USB Start of Frame (SOF) packets sent by the host to the device every 1ms. I’ll show you how to set up this crystal-less configuration later on.

Upon startup the MCU can boot from flash, SRAM or system memory (that’s where the boot loader is). The most common option is to boot from flash directly into your code and you select that by holding BOOT0 low during the exit from reset and standy modes.

But wait, doesn’t this waste the PB8 GPIO pin? No it doesn’t. If you always want to boot from flash then you can program the BOOT_SEL and nBOOT0 bits of theFLASH_OBR register to 0 and 1 respectively and then the MCU will ignore BOOT0 and you can use it as a GPIO pin.

Programming and debugging

ST include an embedded ST-Link/v2 chip on their discovery boards implemented within an STM32F1 series MCU that allows you to program and debug over the same USB line that you use to supply power.

That’s neat, and it means that you don’t have to buy a programmer for your board. It is, however, proprietary which means I can’t include it on this board. Instead, I include the standard 20-pin ST-Link/v2 header that you can attach a programming cable to.

I’ve already written an article about how to set up and use the ST-Link/v2 programmer using only free software.

The USB interface

I’ve opted to include an ST Micro USBLC6-2SC6 ESD protection device between the USB lines and the MCU. Without this the MCU would be vulnerable to ESD events on the line caused by handling of the plug or cable and could easily be damaged or destroyed.

Chances are you don’t even have the ID signal line in your cable (it’s for OTG cables only) but in common with ST’s configuration on their discovery boards I’m grounding it through a 100kΩ resistor.

C1, C2, C3 and FB1 form a filtering network to remove noise from the VBUS line before it becomes an input to the switching regulator. If you’ve never seen how much noise you can get on VBUS then I recommend that you take a look at this article that I wrote.

If you’re powering this board from a computer’s USB port then be mindful of the maximum amount of power that you can draw. This wikipedia article explains it well. Of course if you’re powering this board from a USB wall charger then the limit is set by that charger.

The USB socket itself is a mini-B size and has a very common standard footprint. Search ebay for these mini-B PCB sockets and you’ll see that they all have this footprint.

Power output

P4 is a pin header that can be used to access the power supplies on the board along with a generous helping of ground pins. You can’t have too many ground pins on a development board and I find it really frustrating when you receive a board to find it’s only got one or two ground pins. I’ve included four here and another one on the GPIO header.

NPN transistor

The base of the MMBT3904 transistor is connected via a 1kΩ resistor to PA7 so you can control it as a switch from the MCU. The maximum collector current for the MMBT3904 is 200mA. If you need more than that then you should substitute this part for another one in the SOT23-3 package that has a higher rating.

R9, a 100kΩ resistor, pulls the base down to ground so you don’t get spurious switching events during any periods when the gate is floating. The idea is that you connect your load to be driven to the LOAD pin.

GPIO

All the GPIO pins exposed by the TSSOP20 package are included here as well as the LOAD pin for the NPN transistor and an additional ground pin.

Bill of materials

Here’s the full bill-of-materials for this board, along with Farnell product code numbers to help you put together an order basket.

[1] These components must be rated in excess of the current that you plan to draw. My recommendations support a maximum of 500mA.

[2] 0603 SMD resistors are so cheap on ebay that I recommend you buy some there. I used green for the power LED and amber for the GPIO LED.

[3] The USB mini-B PCB connector is a common footprint that’s very cheaply available on ebay. See the high-resolution photograph in this article and compare to ebay auction photographs.

[4] Dual-row 2.54mm pin headers are very cheap on ebay.

Building the board

The board was laid out to fit within a 50mm square so that it could be manufactured by one of the discount Chinese prototyping houses such as Seeed, ITead, PCBWay and Elecrow. For this size of board I choose Elecrow and for US$9.90 plus delivery I can get ten copies in about two or three weeks.

Time passes. Two or three weeks worth of time as it happens…

I made a small mistake on the Gerbers for the USB connector. On the footprint I include a guideline on one of the mech layers to aid positioning of the connector at the board edge and I mistakenly included that mech layer on the Gerber export with the result being a small sliver of exposed copper at the board edge on both sides under the USB connector. It makes no difference to the viability of the board but I find it annoying because I know it shouldn’t be there!

I’ve included M3 sized screw holes that can be used for adding ‘feet’ to the board so it’s lifted above my work surface and if you look at the back you can see that there are some handy quick-reference tables that identify which pins are connected to the commonly used peripherals.

Now it’s time to build it. I don’t have a paste stencil for this board so I opted to build it in several stages. Firstly I tinned all the surface mount pads with solder. Secondly, I reflowed the larger surface mount components such as all the ICs, the inductor and the USB connector using my bluetooth reflow oven. Thirdly I attached all the smaller 0603 and 0805 components using hot air and tweezers and finally the through-hole components were soldered into place using an iron. A quick wash with hot water and fairy liquid followed by drying overnight and she’s ready to test.

Looking pretty sweet I think. But does it work? Let’s run through some tests to see what it can do.

Testing the functionality

The first test is simply to connect the USB cable from the board to a computer and then test the voltages to make sure the regulator is working. My multimeter read bang on 3.30V from the regulator output and the green power LED, D2, was lit at a nice subtle brightness. Another bugbear of mine is dev boards that include power LEDs configured at retina-burning levels.

Before moving on to a programming test let’s have a look at the residual noise on the board’s 3.3V supply.

It looks reasonable. Noise levels are within +/- 100mV. Let’s get on with some programming tests. I started up OpenOCD from a Cygwin terminal and got the expected output:

Open On-Chip Debugger 0.9.0 (2015-05-19-12:09)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ
       compared to plain JTAG/SWD
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v17 API v2 SWIM v4 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.243836
Info : stm32f0x.cpu: hardware has 4 breakpoints, 2 watchpoints

This means that the MCU is responding to the SWD debugging commands and is ready to program. Now to test the onboard features. I’ll use my stm32plus library for all these tests. Even though it does not directly support the F042 series it does support the F051 and with a few adjustments to startup code and linker scripts we should be able to get things going.

Blinky

The first thing we need to do is modify the linker script designed for the F051 to be compatible with the F042. The section at the top needs to be changed to reflect the 32Kb of flash and the 6Kb of SRAM in the F042. These are the changes:


/* End of 6Kb SRAM */
_estack = 0x20001800;

/* Generate a link error if heap and stack don't fit into RAM */

_Min_Heap_Size = 0;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Specify the memory areas */

MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 32K
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 6K
  MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
}

For now we do not need to modify the code where the core clock is set System.c because it’s already set up to use the PLL fed by the 8MHz HSI. The core clock will be 48MHz.

The onboard LED, D3, is hooked up to PB1. It’s a simple modification to the source code to flash this LED at 1Hz.

void run() {

  // initialise the pin for output

  GpioB<DefaultDigitalOutputFeature<1> > pb;

  // loop forever switching it on and off with a 1 second
  // delay in between each cycle

  for(;;) {

    pb[1].set();
    MillisecondTimer::delay(1000);

    pb[1].reset();
    MillisecondTimer::delay(1000);
  }
}

I fired it up and… success! The amber LED was flashing away at 1Hz. Programming, basic GPIO and the Systick peripheral are all working fine.

The transistor switch

This test is closely related to the basic blinky except this time I connected an external LED and series resistor to the LD (load) pin and change the code to control the blinking to use pin PA7.

It’s working as expected which validates that the NPN transistor is connected up correctly.

What about the external crystal?

I’m not done with the blinkenled just yet. Before I can move on I need to know if the external 8MHz crystal is working which means configuring it as the MCU clock source. Luckily this is really simple.

If you look inside the System.c startup file you’ll see that ST have provided a simple #define to select the clock source. To configure the HSE as the clock source we merely have to change the code to read like this:

//#define PLL_SOURCE_HSI   // HSI (~8MHz) used to clock the PLL, and the PLL is used as system clock source
#define PLL_SOURCE_HSE           // HSE (8MHz) used to clock the PLL, and the PLL is used as system clock source
//#define PLL_SOURCE_HSE_BYPASS  // HSE bypassed with an external clock (8MHz, coming from ST-Link) used to clock
                                 // the PLL, and the PLL is used as system clock source

Testing a timer

The pin that I’ve attached to the LED, PB1, is also the GPIO output for channel 4 of timer 3. It’s a simple task to set up that timer in PWM mode and then to create a quick demo that pulses the LED as smooth ‘heartbeat’.

void run() {

  Timer3<
    Timer3InternalClockFeature,       // the timer clock source is APB1
    TimerChannel4Feature<>,           // we're going to use channel 4
    Timer3GpioFeature<                // we want to output something to GPIO
      TIMER_REMAP_NONE,               // the GPIO output will not be remapped
      TIM3_CH4_OUT                    // we will output channel 4 to GPIO
    >
  > timer;

  /*
   * Set an up-timer up to tick at 12MHz with an auto-reload value of 1999
   * The timer will count from 0 to 1999 inclusive then reset back to 0.
   */

  timer.setTimeBaseByFrequency(12000000,1999);
  timer.initCompareForPwmOutput();
  timer.enablePeripheral();

  /*
   * It's all running automatically now, use the main CPU to vary the duty cycle up
   * to 100% and back down again
   */

  for(;;) {

    // fade up to 100% in 4ms steps

    for(int8_t i=0;i<=100;i++) {
      timer.setDutyCycle(i);
      MillisecondTimer::delay(4);
    }

    // fade down to 0% in 4ms steps

    for(int8_t i=100;i>=0;i--) {
      timer.setDutyCycle(i);
      MillisecondTimer::delay(4);
    }
  }
}

This worked as planned and you can see the pulsating heartbeat LED in the video linked in at the end of this article.

Testing USB

stm32plus currently only has support for USB on the F4 which means that to test the USB interface I’m going to have to hold my nose and dive into that horrendous unreadable mess that’s otherwise known as the STM32 HAL. Taking the ‘custom HID’ example as a starting point, I proceeded to adapt it from the F072 target to the F042 and here’s some lessons I picked up along the way.

Remap PA11 and PA12 to USB_DP and USB_DM

When the MCU starts up PA11 and PA12 are configured for GPIO. The USB D+ and D- lines are actually on PA9 and PA10 and you need to map these two pins in place of PA11 or PA12. If you fail to do this then the USB interrupt will never fire. Here’s how:

// Remap PA11-12 to PA9-10 for USB

RCC->APB2ENR |= RCC_APB2ENR_SYSCFGCOMPEN;
SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;

Way back in this article I promised to show you how to clock the MCU from the internal HSI48 oscillator and then use the SOF frames sent every 1ms by the host to continuously trim the clock to stay in sync with the host. Clocking your MCU like this means that you don’t have to use an external crystal which cuts costs and reduces board space.

Here’s the replacement SetSysClock() function that you can plug into System.c.


void SetSysClock() {

  // enable flash prefetch buffer

  FLASH->ACR |= FLASH_ACR_PRFTBE;

  // enable HSI48

  RCC->CR2 |= RCC_CR2_HSI48ON;
  while((RCC->CR2 & RCC_CR2_HSI48RDY)==0);

  // disable the PLL

  RCC->CR &=~ RCC_CR_PLLON;
  while((RCC->CR & RCC_CR_PLLRDY)!=0);

  // select HSI48 as the USB clock source

  RCC->CFGR3 = (RCC->CFGR3 &~ RCC_CFGR3_USBSW) | RCC_CFGR3_USBSW_HSI48;

  // set flash latency = 1

  FLASH->ACR = (FLASH->ACR &~FLASH_ACR_LATENCY) | FLASH_Latency_1;

  // AHB

  RCC->CFGR = (RCC->CFGR &~ RCC_CFGR_HPRE) | RCC_CFGR_HPRE_DIV1;

  // HCLK source = HSI48

  RCC->CFGR = (RCC->CFGR &~ RCC_CFGR_SW) | RCC_CFGR_SW_HSI48;
  while((RCC->CFGR & RCC_CFGR_SWS)!=RCC_CFGR_SWS_HSI48);

  // PCLK1

  RCC->CFGR = (RCC->CFGR &~ RCC_CFGR_PPRE) | RCC_CFGR_PPRE_DIV1;

  // enable clock recovery system from USB SOF frames

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CRS,ENABLE);

  // Before configuration, reset CRS registers to their default values

  RCC->APB1RSTR |= RCC_APB1RSTR_CRSRST;
  RCC->APB1RSTR &=~ RCC_APB1RSTR_CRSRST;

  // Configure Synchronization input */
  // Clear SYNCDIV[2:0], SYNCSRC[1:0] & SYNCSPOL bits */

  CRS->CFGR &= ~(CRS_CFGR_SYNCDIV | CRS_CFGR_SYNCSRC | CRS_CFGR_SYNCPOL);

  // Set the CRS_CFGR_SYNCDIV[2:0] bits according to Prescaler value
  // CRS->CFGR |= 0;

  // Set the SYNCSRC[1:0] bits according to Source value

  CRS->CFGR |= CRS_CFGR_SYNCSRC_1;

  // Set the SYNCSPOL bits according to Polarity value
  // CRS->CFGR |= 0;

  // Configure Frequency Error Measurement
  // Clear RELOAD[15:0] & FELIM[7:0] bits

  CRS->CFGR &= ~(CRS_CFGR_RELOAD | CRS_CFGR_FELIM);

  // Set the RELOAD[15:0] bits according to ReloadValue value

  CRS->CFGR |= 47999;     // (48MHz/1000) -1

  // Set the FELIM[7:0] bits according to ErrorLimitValue value

  CRS->CFGR |= (0x22 << 16);

  // Adjust HSI48 oscillator smooth trimming
  // Clear TRIM[5:0] bits

  CRS->CR &= ~CRS_CR_TRIM;

  // Set the TRIM[5:0] bits according to RCC_CRS_HSI48CalibrationValue value

  CRS->CR |= (0x20 << 8);

  // Enable Automatic trimming

  CRS->CR |= CRS_CR_AUTOTRIMEN;

  // Enable Frequency error counter

  CRS->CR |= CRS_CR_CEN;
}

With those modifications in place I was able to hack together a build for the ‘custom HID’ example and after a bit of gentle persuasion it actually worked. Here’s the device descriptor dump as reported by the ‘USBView’ Windows debugging utility:

Device Descriptor:
bcdUSB:             0x0200
bDeviceClass:         0x00
bDeviceSubClass:      0x00
bDeviceProtocol:      0x00
bMaxPacketSize0:      0x40 (64)
idVendor:           0x0483 (STMicroelectronics)
idProduct:          0x5750
bcdDevice:          0x0200
iManufacturer:        0x01
iProduct:             0x02
iSerialNumber:        0x03
bNumConfigurations:   0x01

When a USB device is inserted there is a flurry of very fast interrupt-driven data exchange between the host and the device as the host first queries for the device descriptor and then, based on what it receives, comes back with a sequence of further queries for the other standard descriptors. Only if all that goes well will the host accept the device and allow its descriptors to be queried in tools like ‘USBView’.

So now I know that everything on the board works. All the features have been tested and I can happily use it for development and testing on the F042 platform going forward.

Watch the video

There’s a short video to go with this article where I just walk through the board features and then briefly show the programming and demo code.

Lessons learned

When a project comes to a close and you have time to reflect then there’s always one or two things that you’d do differently and this one’s no different. Here are a few things that I’d do differently.

The ‘boot’ selector header is too close to the SWD header. With the SWD cable connected it would be a very tight fit to get a jumper across to select the RAM boot option.

If I were to shuffle a few components around I think I could probably stretch to a push-button on the board. It’s always nice to have a button.

The VDDA selection is a bit clunky. Selecting the internal 3.3V supply as the VDDA source with a jumper is obvious enough but it’s not obvious that to use an external VDDA you have to remove the jumper and connect your external supply to pin 3 in that header block. Pin 4 is effectively redundant.

Breadboard compatibility. If I increased the board size to the 10x5cm format then I’d have enough space to make the pin headers single row and thereby plug directly into a breadboard.

Get the Gerbers

Want to build this board yourself? If you can handle a 0.65mm pitch IC and a generous sprinkling of 0603 passives then you should find this a breeze to build. Head on over to my downloads page to get yourself a copy of gerbers that can be directly uploaded to Elecrow, ITead, Seeed or any other of your favourite prototyping houses.

Bare PCBs for sale

I’ve got quite a few of these blank boards left over from the batch that I received from Elecrow and I’m happy to sell them on a first-come-first-served basis.

Location
Worldwide delivery £3.50 GBP
UK only delivery £2.00 GBP

Final words

That’s all for now, I hope you’ve enjoyed this article and if you’d like to leave a comment then please do so in the comments section below. Alternatively if you got a bit more to say then please head over to the forum and speak your mind!


RFM69 to MQTT gateway using ESP8266

$
0
0

RFM69 to MQTT gateway using ESP8266
Martin / 1 week ago
I’ve mentioned my plans for this project during the IoT hangout session few months ago, it has finally materialized as working prototype. The blocker so far was the lack of ESP8266 RFM69 driver and free time on my end, so I’ve teamed up with Andrey Balarev to solve this. Andrey is an IoT enthusiast + embedded systems developer and has done excellent job in porting LowPowerLab’s RFM69 library for the ESP8266. He spent few weekends staring at the oscilloscope, re-writing SPI library code and managed to solve a number of challenges to get this library going. I’ve bundled his driver code with MQTT to get a beautifully working prototype that forwards RFM69 traffic to MQTT and vice versa. Few screenshots of the setup:

The prototype on veroboard
The prototype on veroboard
The RFM69 configuration UI
The RFM69 configuration UI
Serial debug output
Serial debug output
MQTT broker capture
MQTT broker capture

Some folks probably ask why the RFM69 and not RFM12B and why LowPoweLab’s library and not Jeelib, I’ve outlined my view on that before here. Basically with Jeelib we are forcing the RFM69 in artificial compatible mode and not taking fill advantage of the chip.

What I plan to add as functionality is payload serialization configuration, payload field name configuration and RPN based signal processing configuration so that JSON could be constructed/deconstructed from payloads in both directions.

It will be a replacement for the RFM2Pi project, a much more advanced standalone M2M gateway for the IoT.

I’ll build few PCBs and put some for sale in my shop as well. RFM69 library code will be shared at that point.



An iOS Developer on React Native

$
0
0

An iOS Developer on React Native

When I first caught wind of React Native, I thought of it as nothing more than a way for web developers to dip their feet into native mobile apps. The premise that JavaScript developers could write an iPhone app in JavaScript was definitely something that I thought was really cool, but I quickly shrugged off the idea of using it myself. After all, I had already been doing native iOS development as a hobby for many years, and professionally with Chalk + Chisel (formally Bolster) for almost two years at that point.

I had already made dozens of iOS apps — good apps that I was proud of. Apps built in Xcode and written in Objective-C, because that’s the way it’s always been. That’s what Apple gave us to make iOS apps, so that’s what I and every other developer used. Then, two years ago when Apple released the Swift programming language, I didn’t hesitate to try it out.

It was still in Xcode, and it was still (obviously) Apple-approved for developing iOS apps, so I dove right in and picked it up pretty — ahem — swiftly. I was content in my Apple ecosystem bubble. React Native seemed like a fun little experiment, but in my mind any real native app would still need to be written the real native way. It seemed like a waste of time for me to not only learn JavaScript (I had no experience), but an entirely new way of building apps when I was already beginning to master building them the “real” way.

Fast-forward a couple of months, and I’m confident enough to say I may never write an iOS app in Objective-C or Swift again.

We received a new mobile app project and I reviewed the requirements and designs. Just as I was about to click that beautiful blue Xcode icon to start a new project, our Interactive Director, Adam, walks over and says, “let’s do this one in React Native”.

He explained that part of our contract for this project was to have a clear path going forward to make this app available for Android as well . And although React Native was not yet available for Android, we knew Facebook was actively working on it. Theoretically, if we built the app in React Native for iOS, many parts of it would “just work” on Android by the time it was released.

Well, I wasn’t happy. I felt as if I was at the peak of my iOS development ability and was being asked to throw it all away. I doubted my own abilities to deliver a quality product on time given the inevitable learning curve. But even more than that, I doubted React Native in itself being capable of producing a quality product. Looking back, I don’t even think that doubt was unjustified. At the time, React Native had just come out as a beta. The documentation was lacking, the amount of open sourced React Native libraries and components was minuscule, and example code or Stack Overflow posts for reference were almost nonexistent.

I begrudgingly gave it a shot. But going in with my closed-mind attitude only did more harm. My first hurdle was learning Flexbox, React Native’s way of doing UI layout. Coming from the land of interface builder, laying out UI completely in code frustrated me beyond belief. I struggled to build even the most simple of views.

But it wasn’t just UI — everything was different. That was the biggest point of contention for me.

Every time I got stuck or didn’t understand something, I would tell myself “I could do this in 5 seconds in Objective-C”. Every time I would discover a bug in React Native (and there were a good number), I would think, “this bug doesn’t exist in Objective-C, why am I fighting with it?”

For a solid two weeks I was miserable at work. I had gone from feeling like an expert iOS developer to feeling like I’d never written a line of code in my life. It was defeating, until I took a weekend to clear my head. I took a step back and recognized that Adam had done a lot of research on React Native. I had to trust him as our Interactive Director to not be leading me down a bad path. I vowed to go into work Monday, put my head down, pretend Objective-C and Swift don’t even exist, and figure this thing out.


Learning to Love React

A few weeks ago, we submitted our first React Native app to the App Store. I’m extremely proud of how the app turned out, and I can’t wait to write our next one. In just a little over a month, consider me fully aboard the React Native train. What changed my mind?

The React Paradigm

In React, every piece of UI that is or ever will be lives in the render() method, and is controlled with “state”. Your render() method defines how the UI should look for each state, and upon calling setState(), React figures out what needs to change and does it for you. Imagine a simple view with a label that says “Hello World” and a button. Each click of the button needs to change the label between “Hello World” and “Goodbye World”. In Objective-C, I would need some ugly if statement in my button handler like

if ([label.text isEqual:@”Hello World”]) {
    label.text = @”Goodbye World”;
} else {
    label.text = @”Hello World”;
}

It works fine, but that UI code is completely disjointed from where I created the label in the first place (which could be in code or in interface builder). In React, we would define a buttonClicked bool in our state, our label in render() would look something like:

<Text>
    {this.state.buttonClicked ? ‘Hello World’ : ‘Goodbye World’}</Text>

and our button handler is as simple as:

this.setState({buttonClicked: !this.state.buttonClicked});

All the view code is in one place, and state controls all. This makes comprehending and debugging the code so much easier.

Flexbox

The UI layout tool that I hated so much at first is now one of my favorite things about React Native. I will admit that it is tough to grasp at first, but once you do it makes building UI’s for the variety of different screen sizes extremely fast and easy. I had become addicted to the visual aids of Interface Builder in Xcode. Autolayout now seems overly complex compared to Flexbox. The CSS-esque styling that Flexbox uses makes style reuse as easy as copy paste. And the best part of all allows you to tweak style values to perfection in no time…

Live/Hot Reload

That’s right. Seeing what your button would look like moved over 5 more pixels to the right is as easy as Command+S. React Native can be configured to automatically re-render the current view in the iPhone Simulator without rebuilding the Xcode project. This is huge because not only do you save time by not rebuilding, but you could be working on a view that is nested deep within the app and tweak the UI without having to navigate all the way back to that screen.

Android

It’s still not out yet, but it’s coming — and it’s going to be amazing. I was hesitant about React Native at first because I already liked doing native iOS development. I didn’t have any complaints about it. But I’ve also done native Android development, and it’s not great. React Native will be very welcome on Android, and I am counting down the days until it’s here. This will revolutionize mobile app development by being able to deploy to 2 platforms with 1 code base.

[Update: Since the publication of this post, React Native for Android has been released. To learn more about it, visit: https://facebook.github.io/react-native/]


Retrospective

Missing Xcode

I still miss Xcode, or really just an IDE in general. I’ve worked toward a pretty good React Native development setup, but it wasn’t easy. Sublime Text and a bunch of plugins later and I have good syntax highlighting and linting. Sublime can autocomplete based off other variables and things within the same file, but is lacking some of the robustness of Xcode’s autocomplete. I still have to leave the React documentation up all the time to use as a reference.

Little things like typing React.PropTypes.f and having the IDE not tell me whether I’m looking for ‘func’ or ‘function’ can be bothersome. I also miss Xcode’s version editor — which allowed me to compare a file side-by-side with that file at my last git commit and even undo specific changes on a per line basis. I realize a third party program could help me accomplish this, but one of the great things about IDEs is the all-in-one package.

To run a React Native project, I need to launch my terminal to start the npm packager, Chrome for the debugger, Sublime to edit my code, and ultimately Xcode to run the project and start the simulator. These are all minor complaints in the grand scheme of things, but still a con for me when it comes to React Native. I have high hopes that Nuclide (Facebook’s IDE) will alleviate some or all of these cons.

Bridging

Facebook hasn’t and isn’t going to port every API from iOS to React Native, so for the missing pieces they’ve provided a way to “bridge” things over to JavaScript. Again, when I first got into React Native, the documentation on this was really bad. Every time I realized I needed to bridge something, I wanted to give up on React Native altogether because naturally those things already work in Objective-C. But once they explained the bridging process in more detail, and provided good examples, it wasn’t as intimidating. It still is a hassle, but eventually I could see every bridge imaginable being made open source and available on npm. In fact, most iOS APIs already are.

Bugs, Documentation, Open Source Community

Most, if not all, of my initial complaints about React Native wouldn’t even exist if I started learning it today. Bugs are fixed daily, and new releases seem to pop up every week or so. The documentation still needs work, but has greatly improved. Facebook and the open source community in general are clearly very serious about developing this framework. It’s nice to see people actively engaged in React Native issues on GitHub and questions on Stack Overflow. If you are an iOS developer considering playing with React Native, know that you aren’t alone. React Native is wonderful, and you should try to embrace it with an open mind. Don’t pigeonhole yourself into what is comfortable like I did.

Step outside of your comfort zone and you may just find something even better than before.

Marc Shilling
is an interactive developer at Chalk + Chisel, a digital product agency, in Baltimore, MD.


LoNet 808 – Mini GSM + GPS Board

$
0
0

LoNet 808 – Mini GSM + GPS Board

Description

LoNet 808 is a mini board based on the latest SIM808 module, it offers 2G GSM and GPRS data along with GPS technology for satellite navigation. Also supports assisted-GPS (A-GPS) for indoor localisation.

The board features ultra-low power consumption, working current is low to 1mA when in sleep mode. That gives your the project incredibly long standby times. It uses a serial port communication, supports common 3GPP TS 27.007, 27.005 and SIMCOM enhanced AT commands.  Integrated with battery charging circuit, it is powered by 3.7V Lipo battery and can be charged by 5V micro-USB directly.

It comes with a mini GPS and GSM antenna, however a external Lipo battery is required.

113990107 0

Features

  • Quad-band 850/900/1800/1900MHz
  • GPRS multi-slot class12 connectivity: max. 85.6kbps(down-load/up-load)
  • GPRS mobile station class B
  • Controlled by AT Command (3GPP TS 27.007, 27.005 and SIMCOM enhanced AT Commands)
  • Supports charging control for Li-Ion battery
  • Supports Real Time Clock
  • Supply voltage range 3.4V ~ 4.4V
  • Integrated GPS/CNSS and supports A-GPS
  • Supports 3.0V to 5.0V logic level
  • Low power consumption, 1mA in sleep mode
  • Supports GPS NMEA protocol
  • Compact size 27mm x 46mm x 10mm
  • Standard SIM Card

GPS  Features

  • Receiver channels: 22 tracking / 66 acquisition
  • Coarse/Acquisition code: GPS L1
  • Tracking sensitivity: -165dBm
  • Cold start time: 30s (typ.)
  • Hot start time: 1s (typ.)
  • Warm start time: 28s (typ.)
  • Horizontal position accuracy: < 2.5m CEP
  • Power consumption – Acquisition: 42mA
  • Power consumption – Continuous tracking: 24mA
  • Update rate: 5Hz

Related Products

Hardware Interface

top

  1. Power Button – this is the hard power switch for the module. When the module is power up, you can turn on or turn off the module by pressing the button for 2s.
  2. Li-ion Battery – this is power supply for the module, input voltage is from 3.4V to 4.4V. It uses the JST-2.0mm connector, that make it convenient to connect to 3.7V Li-Po Battery.
  3. MicroUSB – the charging interface for Li-Ion battery, of input voltage range from 5V to 7V.
  4. GSM Antenna – this is an uFL GSM antenna connector, just connect it to a GSM antenna for receiving GSM signal.
  5. GPS Antenna – this is an uFL GPS antenna connector. You can connect either passive or active GPS antenna to it. Active GPS antenna runs at 2.8V voltage.
  6. Net Indicator – Red LED, it will tell the what status is about the module linking to network.
  7. Status Indicator – Green LED, it will tell whether the module is on, light when the module is running.
  8. Breakout Pin – see Pin Definitions for more details.
  9. SIM – Card Holder – SIM card holder for standard SIM card
  10. Power Supply Pin – used for power soldering and testing.

Pin Definitions

NAME I/O DESCRIPTION NOTE
BAT I/0 Power input / output 3.4V – 4.4V DC
GND I/0 Power ground / logic ground
VIO I Logic level reference 2.8V – 5.0V DC
DTR I Sleep mode controlled pin Pull high for sleep mode
PWR O Power switch Active low in 2s
RI O Event/ message pin
TXD O Transmit data UART output from SIM808
RXD I Receive data UART Input to SIM808
RST I Reset pin Active low

Pin Description

  • PWR – this is soft power switch for the module, you can pull it to high level for at least 2s to power up or power down the module.
  • RI – this pin will tell you whether the module is on and is there any calls and messages received. It will be pulled to high level when the module is on. And it will change to low for 120ms when a call or message is received.
  • RST – this is reset pin for the module. By default it has a high pull-up. If you absolutely got the module in a bad space, you can pull it to low level for 100ms to perform a hard reset.
  • RXD / TXD – Serial port, the module uses it to send and receive commands and data. TXD is output, and RXD is input. They can be connected to the 3.3V and 5V level.
  • VIO – this is the reference logic level for serial port of the module, the input voltage depends on the logical level of the miccontroller you use. If you use a 5V miccontroller like Arduino, you should have it be 5V, and a 3V logic miccontroller you should set it to 3V.
  • BAT – this pin is connected to Li-Ion battery pin, if you want to use only one Li-Ion battery as your power supply, you can use it to drive you microcontroller.
  • DTR – this is wake up pin for module in sleep mode. By default it has a high pull-up, and you can set the module into sleep mode by AT command “AT+CSCLK=1”. In the meantime, the serial port will be disabled. To wake up the module and enable serial port, you can pull this pin to low level for about 50ms.

Indicator LEDs

INDICATOR LEDS STATUS BEHAVIOR
Operating Status (Green) Off SIM808 is not running
On SIM808 is running
Network Status (Red) Off SIM808 is not running
64ms on/ 800ms Off SIM808 not registered to the network
64ms On/ 3000ms Off SIM808 registered to the network
64ms On/ 300ms Off PPP GPRS communication is established

Reference Circuit

Connect to Microcontroller

CONS1-01

Connect to PC

CONS2-01

Testing AT Command with Arduino

// this sketch is used for testing LoNet with Arduino

// Connect VIO to +5V
// Connect GND to Ground
// Connect RX (data into SIM800L) to Digital 11
// Connect TX (data out from SIM800L) to Digital 10

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  mySerial.begin(9600);

}

void loop() // run over and over
{
  if (mySerial.available())
    Serial.write(mySerial.read());

  if (Serial.available())
  {
    while(Serial.available())
    {
      mySerial.write(Serial.read());
    }
    mySerial.println();
  }
}

Set Baud and Enable Charging Function

It is recommended to execute this process when first time to use the module. In the Serial Monitor columns of tables, input of AT commands are in back, module returns values are in orange.

SERIAL MONITOR DESCRIPTION
AT
OK
Send command “AT” to synchronize baud rate. Serial port of module is by default set at auto-baud mode, and in this mode, it will not output any indications when the module is on.
AT+IPR=9600
OK
Set baud rate at 9600bps, supports baud rate from 1200bps to 115200bps.
AT+ECHARGE=1
OK
Send command “AT+ECHARGE=1” to enable battery charging function. By default the charging function is closed.
AT&W
OK
Save parameter setting.
AT+CPOWD=1
NORMAL POWER DOWN
Power down the module.
RDY
+CFUN: 1
GPS Ready
+CPIN: READY
Call Ready
SMS Ready
Turn on the module again by the power button, it will response status about GPS and GSM.
AT+CBC
+CBC: 1,96,4175
OK
Inquire charging status and remaining battery capacity.
AT+CSQ
+CSQ: 14,0
OK
Inquire GSM signal quality.

Get location with GPS

SERIAL MONITOR DESCRIPTION
AT+CGPSPWR=1
OK
Open GPS
AT+CGPSSTATUS?
+CGPSSTATUS: Location Not Fix
OK
Read GPS fix status, “Location Not Fix” means that positioning is not successful. For the first time to start, it will take at least 30s. GPS must be tested by the window or outdoor.
AT+CGPSSTATUS?
+CGPSSTATUS: Location 3D Fix
OK
GPS has fixed with 3D status.
AT+CGPSINF=0
+CGPSINF:
0,2234.931817,11357.122485,
92.461185,20141031041141.000,
88,12,0.000000,0.000000
Get the current GPS location information. Parameters formate: <mode>, <altitude>, <longitude>, <UTC time>, <TTFF>, <num>, <speed>, <course>
AT+CGPSOUT=32
OK
$GPRMC,043326.000,A,
2234.9414,N,11357.1187,E,
0.000,143.69,311014,,,A*50
Read NMEA $GPRMC data, of which, “2234.9414 N, 11357.1187 E” is the location coordinates. For more details about NMEA sentences, check this site.
AT+CGPSRST=0
OK
Reset GPS in Cold Start Mode.
AT+CGPSRST=1
OK
Reset GPS in Hot Start Mode.
AT+CGPSPWR=0
OK
Close GPS.

Downloads

Related Resources

Support

Any question, document mistakes and suggestions , please contact deray@deegou.com.

We are not good at programming,  for basis questions we will try to help. But for complex problem, we may not be able to help.

To the end, thank you for your reading.


C.H.I.P Simple GPIO Experiments

$
0
0

Simple GPIO Experiments

CHIP has several General Purpose Input/Output (GPIO) pins available for you to build around. If you want to access them in a very primitive way, just to confirm their existence, here’s some things to try.

How You See GPIO

There are eight (8) GPIO pins always available for connecting CHIP to the sense-able world. These are in the middle of the right header, U14, Pins 13-20, labeled XIO-P0 to P7:

How The System Sees GPIO

There is a sysfs interface available for the GPIO. This just means you can access the GPIO states in a file-system-like manner. For example, you can reference XIO-P0 using this path:

/sys/class/gpio/gpio408/

which you can see is somewhat unfortunate, since the sysfs names do not match the labels on our diagram! But is not too hard to translate. PinsXIO-P0 to P7linearly map to gpio408 to gpio415.

Some GPIO Switch Action

These lines of code will let us read values on pin XIO-P7. First, we tell the system we want to listen to this pin:

echo 415 > /sys/class/gpio/export

View the mode of the pin. It should return “in”:

cat /sys/class/gpio/gpio415/direction

Connect a jumper wire between Pin 20 (XIO-P7) and Pin 39 (GND). Now use this line of code to read the value:

cat /sys/class/gpio/gpio415/value

Some GPIO Output

You could also change the mode of a pin from “in” to “out”

echo out > /sys/class/gpio/gpio415/direction

Now that it’s in output mode, you can write a value to the pin:

echo 1 > /sys/class/gpio/gpio415/value

Enough IO

When you are done experimenting, you can tell the system to stop listening to the gpio pin:

echo 415 > /sys/class/gpio/unexport

Learn More

You can learn a bit more about GPIO and Linux here:https://www.kernel.org/doc/Documentation/gpio/sysfs.txt

Have more questions? Submit a request

0 Comments

Please sign in to leave a comment.

使用 JS 构建跨平台的原生应用 React Native for Android

$
0
0

使用 JS 构建跨平台的原生应用(一):React Native for Android 初探

2015-12-02 08:03 编辑: cocopeng 分类:Android相关 来源:淘宝FED
0 432

Facebook 于 2015 年 9 月 15 日推出 React Native for Android 版本。相比起 for iOS,for Android 跑 “Hello, World!” 折腾了不少。在这些复杂的环境、工具依赖里,我们可以看出 React Native for Android 的一些端倪。

本系列文章就以开发一个 “Hello, World!” 的 App 为线索,跟大家一起来了解 React Native for Andorid 的技术背景。

  • 本文以在 OS X 开发为例
  • React Native 的更新非常活跃,本文以 0.14.0 版本为例
  • 下文简称 React Native 为 RN
  • 下文部分链接访问需要翻墙

基础环境

  • 在开始 RN 开发之前,我们需要在自己的机器上准备基础的开发环境:Homebrew
  • OS X 不可或缺的套件管理器,待会我们会用到它来安装nvm。

nvm:$ brew install nvm

  • nvm 是 Node.js 的版本管理器,可以轻松安装各个版本的 Node.js

Node.js:$ nvm install node && nvm alias default node

需要 4.0 或以上。RN CLI 使用到了 ES6 的语法特性

TB1FBm9KpXXXXXCXVXXXXXXXXXX-1224-668.jpg

RN 官方还推荐我们安装 2 个工具包,这是可选的,它们分别是:

Facebook 出品的文件监控工具,如果你安装了它,RN 会用它来检测文件变化,以便重新编译。如果你没有安装,会默认使用 walker

TB1Qr5jKpXXXXbXXpXXXXXXXXXX-1574-963.jpg

flow:$ brew install flow

Facebook 出品的 JS 静态类型的检查器

如果你安装了 watchman 又版本太低,那么编译项目的时候可以能会报错 Cannot read property ‘root’ of null ,所以如果安装了 watchman 请运行 $ brew update && brew upgrade 确保使用最新版本。

Android 开发环境

Android 应用程序开发中,通过在 Android SDK(Android 软件开发包)中使用 Java 作为编程语言来开发应用程序(开发者亦可以通过在 Android NDK(Android Native 开发包)中使用 C 语言或者 C++ 语言来作为编程语言开发应用程序)。

此外,Google 还推出了 Android Studio ,是一个为 Android 平台开发程序的集成开发环境(对比 iOS 的 Xcode)。

现在就来开始准备 Android 的开发环境:

SDK 指 Software Development Kit,软件开发工具包

这里安装的是Stand-alone Android SDK Tools,基础的 SDK 工具。默认情况下,这个 SDK 并不包括着手开发所需的一切内容。Android SDK 将工具、平台和其他组件分成若干个软件包,可以通过 Android SDK 管理器根据需要下载这些软件包。因此需要先为 Android SDK 添加几个软件包,然后才能着手开发。

选择以下包进行添加安装:命令行下运行 $ android 来打开 SDK Manager

Android SDK Tools

  • Android SDK 扩展工具包,它与具体 Android 平台无关,包括一套完整的开发和调试工具。
  • 包位置:$ANDROID_HOME/tools
  • 主要工具:ant scripts (to build your APKs) and ddms (for debugging)
  • 更新历史:http://developer.android.com/tools/sdk/tools-notes.html

Android SDK Platform-tools

  • 平台相关性工具,支持最新 Android 版本功能的同时向下兼容。
  • 包位置:$ANDROID_HOME/platform-tools
  • 主要工具:adb (to manage the state of an emulator or an Android device)

Android SDK Build-tools

Android 6.0(API 23) – SDK Platform

Android Suppor Repository

安装包图示:

QQ截图20151201182310.jpg

  • 设置环境变量 ANDROID_HOME

RN 内使用该变量进行 Android SDK 查找,代码如下:

TB1pGG6KpXXXXayXVXXXXXXXXXX-1170-721.jpg

因此你需要设置此环境变量:

1. 打开一个 Terminal 窗口,运行 `export ANDROID_HOME=/usr/local/opt/android-sdk`

2. 把上面的命令粘贴到`~/.bashrc`,`~/.bash_profile` 这样每次 Terminal 启动都会自动赋值 ANDROID_HOME 了

运行环境

完成了开发环境的准备,接下来我们需要准备应用的运行环境(类似于我们进行前端开发时需要在本机安装一个浏览器来运行我们的代码),这里有 2 种方式:

模拟器

第一种方式是在本机安装 Android 模拟器,模拟一个 Android 系统。

这里推荐使用 Genymotion,个人用户免费的模拟器。

  • 下载 VirtualBox
  • 下载 Genymotion
  • 打开 Genymotion,点击 “Add” 创建一个模拟设备
  • 刚才我们安装了 Android 6.0(API 23) – SDK Platform ,所以请确保你创建的虚拟设备 Android 版本不会大于这个
  • 选择模拟设备,点击 “Start” 启动一个模拟设备

真机

除了模拟器,我们还可以在手机上使用 USB 调试模式把自己的应用运行在这个真机环境里。

  • 设置你的手机允许USB 调试
  • 使用 USB 连接你的手机和电脑
  • 运行命令 $ adb devices 查看当前可用设备,确认调试连接是否成功。如果成功在列表下将会出现你的设备

开始你的第一个 RN for Android 应用

万事具备,开始用 RN 新建一个 Android 应用并且让它在你准备的运行环境里跑起来吧。

安装 RN 脚手架

1
$ npm install -g react-native-cli

react-native-cli(0.1.7) 只是一个外壳,实际执行的代码是在:react-native/local-cli/cli.js

TB1BQnpKpXXXXbRXXXXXXXXXXXX-810-698.jpg

初始化一个 RN 项目

1
$ react-native init AwesomeProject
  • 打开 AwesomeProject/index.android.js ,修改 Text 标签内的文案为 Hello, World!

TB154ThKpXXXXXHXFXXXXXXXXXX-983-609.jpg

启动调试

在 AwesomeProject 项目目录运行 $ react-native run-android,如果你使用的运行环境是模拟器,如无意外,你将会在你的模拟器上看到这个画面:

QQ截图20151201182814.jpg

本篇文章跟大家一起“浅出”了 RN for Android ,下一篇将与大家一起“深入”:

react-native run-android 的背后到底发生了什么?

将涉及到 RN 的 JS 打包构建流程和 Android SDK 的 workflow。

使用 JS 构建跨平台的原生应用(二):React Native for Android 调试技术剖析

2015-12-03 09:39 编辑: cocopeng 分类:Android相关 来源:淘宝FED
0 204

react-native run-android 这个调试命令的背后涉及到 RN 的整个执行流程,值得进行剖析。

  • React Native 的更新非常活跃,本文以 0.14.0 版本为例
  • 下文简称 React Native 为 RN
  • 下文部分链接访问可能需要翻墙

run-android

react-native run-android 命令启动后你能看到:

  • 当前窗口编译打包了一个 Android apk 并且把它安装、运行在了虚拟机环境里
  • 新开一个命令行窗口起了一个 HTTP 服务在监听 8081 端口

前者好理解,后者是为什么呢?

还记得我们上文修改的 index.android.js 文件吗?它是应用的 JS 入口文件。为方便调试,RN 将编译打包一个 debug 版本的 APK 把它安装到虚拟机环境,App 内是靠发送 HTTP 请求到开发机上获取这个 JS

文件来进行 UI 渲染的:

TB1Lp3NKpXXXXXbXFXXXXXXXXXX-844-559.jpg

那么这两步在 RN 内是如何实现的呢?

react-native 命令执行的是上文安装的 react-native-cli,但这个包没有做实际的事情,真正执行的代码是在 react-native 这个库的 local-cli 文件夹里。

就拿 react-native run-android 来说,它实际执行的代码是react-native/private-cli/src/runAndroid/runAndroid.js

执行后,命令行窗口的输出如下:

QQ截图20151201183644.jpg

这两个输出寓意着 RN 要执行的两个函数:

  • startServerInNewWindow
  • buildAndRun

TB1L0ZkKpXXXXbOXXXXXXXXXXXX-1009-206.jpg

启动 HTTP 服务在新窗口

startServerInNewWindow 的执行效果跟在项目根目录下运行 node start 是一样的,都会去调用 react-native/private-cli/src/server/server.js,其调用过程如下:

TB19rglKpXXXXbyXXXXXXXXXXXX-1019-450.jpg

我们真正需要关心的是 react-native/private-clil/src/server/runServer.js 这个文件里的内容:它将创建一个 HTTP 服务并默认监听 8081 端口:

1
2
3
4
5
6
7
8
9
//react-native/private-cli/src/server/runServer.js
const connect = require('connect');
const http = require('http');
function runServer(args, config, readyCallback) {
    const app = connect()
        //code...
      return http.createServer(app).listen(args.port, '::', readyCallback);
}
module.exports = runServer;

接下来,我们以 startServerInNewWindow 唤起的命令行窗口内的输出为线索,了解启动这个 HTTP 服务背后做了些什么:

TB11MfxKpXXXXbRXFXXXXXXXXXX-1000-890.jpg

窗口内有8个输出,它们分别是(见括号数字):

createServer

  • Building Dependency Graph(1)
  • Crawling File System(2)
  • Building in-memory fs for JavaScript(4)
  • Building Haste Map(5)
  • Loading bundles layout(3)

processRequest

request:/index.android.bundle?platform=android&dev=true(6)

  • find dependencies(7)
  • transform(8)

(1)-(5)是服务启动阶段中主动的 console ,(6)-(8)是 App 访问服务时触发的 console 。

创建一个响应对象

TB1IA3eKpXXXXXDXFXXXXXXXXXX-1007-239.jpg

(提示:通过上图我们可以得知,程序执行流程掉入了 /packager 这个文件夹里。这是一个重要的文件夹,它的职责是打包 JS 。它是独立于平台的,无论是 Android 还是 iOS ,都会调用它去进行打包 JS 的工作)

HTTP 服务启动过程中,将会创建多个响应中间件,其中有一个最重要的中间件就是 ReactPackagerMiddleware。这个中间件就是响应后面我们 buildAndRun 流程里创建并运行在虚拟环境内的 App 发送的 request:/index.android.bundle 请求的。

ReactPackagerMiddleware 将创建一个 Server 对象,Server 则会创建 Bundler 对象,它的作用如名字一样,负责具体的 JS 打包工作。

但在启动服务的这一步,Bundler 主要做的是准备工作:它会在内存建立 DependencyResolver,方便将来打包时可以快速地操作文件。

构建依赖树

DependencyResolver 的调用栈如下:

递归项目目录找出所有文件

在内存内文件系统,将项目目录下的 .js .json 文件以依赖树状结构存储到上面

快速索引文件系统,里面会排除掉 node_modules/

挂载响应

Server 对象创建完毕,程序将 Server 的 processRequest 方法作为一个响应中间件挂载到刚启动的 HTTP 服务上用于响应请求:

1
2
3
4
exports.middleware = function(options) {
  var server = createServer(options);
  return server.processRequest.bind(server);
};

自此,前期工作已经准备完毕。后面(6)-(8)输出,则是来自于 App 请求 /index.android.bundle?platform=android&dev=true 的响应。

响应请求

安装和运行到虚拟机环境里的 App 在启动完成后会发送一个 HTTP 请求到 http://yourDevIP:port/index.android.bundle?platform=android&dev=true 以获取 bundle 资源。

Server.processRequest 捕获到这个请求,并且响应一个打包好的 JS 文件:

TB1ydg1KpXXXXXQXXXXXXXXXXXX-678-822.gif

前面介绍过,Server 在初始化时会创建一个 Bundler 对象,而在收到请求后 Server 就是用这个 Bundler 进行打包 JS 文件的。

最后的控制台输出告诉了我们 Bundler 的打包过程:

  • find dependencies(7):在 Bundler 创建时生成的 DependencyResolver 查找依赖关系树
  • transform(8):将查找到的 JS 模块进行编译

有关于 build 的全过程,我将在未来的文章中更深入地进行讲解,现在你只需要知道:

TB1jpcVKpXXXXXXXpXXXXXXXXXX-1018-609.gif

热部署技术

Reload JS

TB1dAb1KpXXXXbGXXXXXXXXXXXX-550-743.gif

在虚拟机环境内,打开 App 的菜单,点击 Reload JS ,如果开发机脚本有被修改,则 App 内 UI 会重新渲染。这是怎么做到的呢?

原来,点击 Reload JS 后,App 会重新发送 HTTP 请求到开发机,开发机上的服务器收到请求后根据参数决定是否重新 build 返回 bundle 文件。

Auto reload on JS change

TB1ElvuKpXXXXXaapXXXXXXXXXX-550-743.gif

Reload JS 通过重新发送请求就能做到了,那在 Dev Settings 中设置 Auto reload on JS change 选项后,每次开发机 JS 代码有改动,App 内 UI 就会重新渲染,这又是怎么做到的呢?

Dev Settings 更新后将会触发 App 内的 reload 方法,reload 时将会去检查当前的 mDevSettings 内有无开启 Auto reload on JS change ,如果有,则开启轮询 startPollingOnChangeEndpoint:

TB1OXoGKpXXXXboXFXXXXXXXXXX-932-688.gif

startPollingOnChangeEndpoint 将启动一个 HTTP 客户端然后发送请求到http://yourDevIP:port/onchange

TB1iN7qKpXXXXaQaXXXXXXXXXXX-946-801.gif

无论请求成功还是失败,App 都会继续通过这个 HTTP 客户端发送同样的请求(轮询):

TB1QpwTKpXXXXcAXXXXXXXXXXXX-946-819.gif

而如果请求返回的状态码是 205,则调用 mOnServerContentChangeListener.onServerContentChanged 做出响应,onServerContentChanged 会做的动作则是 handleReloadJS, handleReloadJS 这一步则会如 App

初始化时的一样,发送一个 HTTP 请求到 http://yourDevIP:port/index.android .bundle?platform=android&dev=true 获取最新的 bundle 并且进行编译渲染。

TB1xx.gif

接下来看看开发机上的 HTTP 服务接收到 /onchange 请求将会做出怎样的响应:

  • 服务器接受到 /onchange 的请求后没有做成任何响应,而是默默地把请求通过 _processOnChangeRequest 方法存储在了 Server._changeWatchers 中。当请求太久没有响应而超时关闭时,就把 Server._changeWatchers 清空:

TB1V6QGKpXXXXcXXFXXXXXXXXXX-671-487.gif

TB1bi.gif

  • 在服务器收到 /onchange 请求时,直到关闭这个请求的过程前,如果服务器内的 JS 文件发生任何变更,服务器将会重新 build 并且响应这个 /onchange 。这里就涉及到 FileWatcher 模块的引入:在 Server 初始化时,引入了 FileWatcher 模块并把它传递给了 Bundler 。还记得上一节中我们讲过的吗?Bundler 会初始化 DependencyResolver ,在这一步里,Bundler 会使用 FileWatcher 监听依赖树里的每一个文件,当它们发生变化时,FileWatcher 会抛出相应的事件。

TB10fILKpXXXXcGXpXXXXXXXXXX-666-417.gif

  • Server 内,监听了 FileWatcher 的事件,接受到事件后,进行 rebuild ,响应 /onchange 请求:

TB1SGEsKpXXXXXYaXXXXXXXXXXX-747-832.gif

至此,用一张图来总结 startServerInNewWindow 的执行流程:

TB1nNQTKpXXXXXNXpXXXXXXXXXX-1018-596.gif

编译和运行应用

另外一边,RN CLI 编译打包了一个 APK 并且把它安装运行在了虚拟机内。观察 Shell 的输出:

QQ截图20151202113227.gif

定位到 buildAndRun 的源码:

TB1Gh.gif

由此可得知,编译打包安装、运行 App 是分 2 步来执行的,最终执行的命令是:

QQ截图20151202113341.gif

Gradle:编译、打包、安装

cd android && ./gradlew installDebug

最终执行的命令是:

1
2
3
java -Xdock:name=Gradle -Xdock:icon=
/android/media/gradle.icns -Dorg.gradle.appname=gradlew -classpath
/android/gradle/wrapper/gradle-wrapper.jar org.gradle.wrapper.GradleWrapperMain installDebug

原来,RN 中打包编译是由 Gradle Wrapper 来实现的。Gradle Wrapper 是一种方便的使用 Gradle 的方法,他包括了为支持 Windows 的批处理脚本和支持类 Unix 的 shell 脚本。这些脚本在不安装 Gradle 时候,也可以用 Gradle。

通过 /android/gradle/wrapper/gradle-wrapper.properties 我们还可以知道 RN 使用的是 2.4 版本的 Gradle 。

接下来针对 Gradle 做一个简单的介绍。

Gradle 是什么?

参考它官网的介绍:

Gradle is a build tool with a focus on build automation and support for multi-language development.

Gradle 遵循约定优于配置的原则,它的主要配置文件是 build.gradle 。打开/android/ 文件夹,就可以看到这个配置文件:

├── app

├── build

├── build.gradle

├── gradle

├── gradle.properties

├── gradlew

├── gradlew.bat

└── settings.gradle

Projects 和 tasks

Gradle 里的任何东西都是基于这两个基础概念:

  • projects(项目)
  • tasks(任务)

每一个构建都是由一个或多个 projects 构成的。一个 project 到底代表什么依赖于你想用 Gradle 做什么。举个例子,一个 project 可以代表一个 JAR 或者一个网页应用。它也可能代表一个发布的 ZIP 压缩包, 这个 ZIP 可能是由许多其他项目的 JARs 构成的。但是一个 project 不一定非要代表被构建的某个东西。它可以代表一件要做的事,比如部署你的应用。

每一个 project 是由一个或多个 tasks 构成的。一个 task 代表一些更加细化的构建。可能是编译一些 classes,创建一个 JAR, 生成 javadoc,或者生成某个目录的压缩文件。

我们来看一下 RN Andorid 下有多少个 project,运行 gralde projects (使用 brew install gralde 安装 gralde CLI)

TB1DQ3JKpXXXXX8XFXXXXXXXXXX-651-295.jpg

可见我们有 2 个 project ,一个是根项目 AwesomeProject,另一个是其子项目 app 。 这是在 /android/settings.gradle配置的。 Gradle 将会根据 project 文件夹内的 build.gradle 依次执行构建。

接下来看看我们有哪些 tasks,运行 gralde tasks:

TB1b2gzKpXXXXXtXVXXXXXXXXXX-654-820.gif

tasks 比较多,不一一展开,重点是,找到了我们此次运行的 task:installDebug

这个 tasks 来自于哪里?它是在哪里定义的?你会发现,你搜遍你的项目文件夹,也没有找到这个 task 定义的地方。

原来,Gradle 有一个插件机制,/android/app/build.gradle 中有这一行代码:

apply plugin: “com.android.application”

它加载了 Android Plugin for Gradle ,installDebug 正是它提供的一个 task。

build.gradle

gradle 命令会在当前目录中查找一个叫 build.gradle 的文件。我们称这个 build.gradle 文件为一个构建脚本 (build script), 但是严格来说它是一个构建配置脚本 (build configuration script)。这个脚本定义了一个 project 和它的 tasks。

我们的 android 项目有两个 build.gradle 对应着两个 project,分别是:

关于这 build.gradle 内配置项的介绍,请阅读:《Configuring Gradle Builds》 。这里我们需要了解的是,我们的 JS 资源打包时如何进行配置的。

/android/app/build.gradle 中加载了/android/app/react.gradle,正是这个文件内的配置把 bundleDebugJsAndAssets 的逻辑添加进了 android build process :

1
2
3
4
5
6
7
8
9
10
gradle.projectsEvaluated {
    // hook bundleDebugJsAndAssets into the android build process
    bundleDebugJsAndAssets.dependsOn mergeDebugResources
    bundleDebugJsAndAssets.dependsOn mergeDebugAssets
    processDebugResources.dependsOn bundleDebugJsAndAssets
    // hook bundleReleaseJsAndAssets into the android build process
    bundleReleaseJsAndAssets.dependsOn mergeReleaseResources
    bundleReleaseJsAndAssets.dependsOn mergeReleaseAssets
    processReleaseResources.dependsOn bundleReleaseJsAndAssets
}

由于我们执行的是 ./gradlew installDebug ,这是 debug 模式,所以 bundleDebugJsAndAssets 默认是不执行的

1
enabled config.bundleInDebug ?: false

所以说在 ./gradlew installDebug 时,默认不会打包 JS 。

RN android 的编译打包和普通 android 应用没有区别,Android 的开发体系非常庞大,在这篇文章中不再展开,编译打包的具体流程可通过下图概括:

TB1FqqHJVXXXXbnaXXXXXXXXXXX-536-882.gif

(图片来源:http://developer.android.com/sdk/installing/studio-build.html

打包成功后的 APK 文件在 /android/app/build/outputs/ ,然后 Gradle 会查找当前的虚拟设备,把该 APK 安装到上面。

Native 入口

./gradlew installDebug 没有打包 JS 资源,那我们的应用是怎样加载 JS 呢?

正像我们一开始说的那样,debug 版的 App 是通过去访问开发机上的服务器去获取 JS 资源的。RN Andorid 分为几步来实现:

  • App 程序主入口 MainActivity 在 debug 模式时开启 DeveloperSupport:
1
ReactInstanceManager.builder().setUseDeveloperSupport(BuildConfig.DEBUG)
  • ReactInstanceManager(构建 React 的运行环境,发送事件到 JS, 驱动整个 React 的运转。 通过 builder 可以创建不同的 React 环境:例如内置 JS 文件路径, 开发环境 dev 的 JS 名字,是否支持调试等):创建 DevSupportManager:
1
mDevSupportManager = new DevSupportManager(...);

ReactRootView(Android 标准的 FrameLayout 对象,另外一个功能是提供 React 入口):初始化 React 世界:

1
mReactInstanceManager.attachMeasuredRootView(this)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void createReactContextInBackground() {
    if (mUseDeveloperSupport) {
      if (mDevSupportManager.hasUpToDateJSBundleInCache()) {
        // If there is a up-to-date bundle downloaded from server, always use that
        onJSBundleLoadedFromServer();
        return;
      else if (mBundleAssetName == null ||
          !mDevSupportManager.hasBundleInAssets(mBundleAssetName)) {
        // Bundle not available in assets, fetch from the server
        mDevSupportManager.handleReloadJS();
        return;
      }
    }
    // Use JS file from assets
    recreateReactContextInBackground(
        new JSCJavaScriptExecutor(),
        JSBundleLoader.createAssetLoader(
            mApplicationContext.getAssets(),
            mBundleAssetName));
}

参考资料

Gradle User Guide

Gradle Plugin User Guide

Android Plugin for Gradle

总结

本篇文章跟大家一起深入了解了react-native、run-android背后的执行逻辑,通过对此的学习,我们基本了解了:

  • RN JS 层面的打包流程
  • RN android 应用的打包流程和技术背景

题图:不可阻挡的阳光。


Friends – Connecting Meteor and React Native by example

$
0
0

Friends – Connecting Meteor and React Native by example

Today we’ll take a closer look into the world of app development with React Native and Meteor.

Introducing “Friends”

“Friends” is a sample application which is available on GitHub and uses React Native in combination with Meteor to show you a list of friends which is reactive and updates automatically when friends are added, updated or removed.

kzxVHARI8p

How is this done?

I recommend you to take a look at the commits on GitHub where I’ve explained how to develop this application step by step.

Additionally here’s a rough explanation what these application do and how they interact with each other:

A basic Meteor application acts as a server and data store for your list of friends.
Some example friends are inserted when the Meteor application is started. A publication makes it possible for other clients to subscribe to a list of friends via DDP.

The React Native app subscribes to the friends publication through DDP and renders the friends on a ListView.

Why React Native?

React Native is a very young, but also promising technology. The main selling point of React Native is the JavaScript approach which makes it easy for you to develop Android and iOS application with the help of pure JavaScript. As a Meteor developer you don’t have to switch between JavaScript and Objective-C / Swift anymore. I’ve you’re experienced with React components it will be even easier as React Native uses React components as a view layer.

Conclusion

Meteor and React Native is a great fit. If you want to develop reactive apps in one language you should definitely give it a try and tinker around. It’s impressive how easy you can develop iOS or Android applications if you have a basic understanding of React!


C.H.I.P. vs Pi Zero: Which Sub-$10 Computer Is Better?

$
0
0

$5 Pi Zero and $9 C.H.I.P. with banana for scale. Photography by Hep Svadja

Now that there are two capable, sub-$10 computers for Makers — the $5 Pi Zero and the $9 C.H.I.P. — the debate will rage online over which board is faster, cheaper, and the right one to use in a project. These debates are often unproductive, but they don’t have to be. Let’s take a look at some of the pros and cons of each board.

SPECS COMPARISON

The main processor of the Pi and C.H.I.P. are fairly evenly matched, both operate at 1GHz with 512MB or RAM, but the C.H.I.P. uses the newer ARMv7 architecture (the Pi Zero uses an older ARMv6 architecture, which is confusingly also called ARM11). They each are powered using USB, but C.H.I.P. can also be powered using a Lithium Polymer battery and has built-in charging circuitry. Pi Zero requires a microSD card to act as storage space for an operating system and applications; the slot allows for swappable software and memory expansion at the same size. C.H.I.P. has onboard 4GB of NAND flash storage, and ships with an operating system preloaded in the memory. To go bigger, you have to use USB (a faster interface than the SD card) and an external drive or storage device.

piside1

Pi Zero provides an unpopulated 40-pin connector for input and output (I/O). Whereas C.H.I.P. offers two rows of 40-pin female headers — 80 total I/O — for easily accessible I/O. HDMI mini provides video output on the Pi, and composite video output is possible, but requires aftermarket soldering. C.H.I.P. lacks HDMI — though an HDMI accessory board is available — but has composite video output through the TRRS jack (it looks like a headphones jack).

CHIP , the $9 computer ships

The biggest difference between the two boards is with connectivity. C.H.I.P. has built-in Wi-Fi and BLE; the Pi Zero has no way to access the internet without additional accessories. Solving this lack of connectivity makes the cost of owning a Pi Zero increase greatly. It’s not just that you need a USB Wi-Fi dongle, you’d need a powered USB hub to have a Wi-Fi dongle, keyboard, and mouse (it only has one USB slot for peripherals; the other is for power).

Kiwi for scale, with Pi Zero and C.H.I.P. Photography by Hep Svadja

DIFFERING DESIGN APPROACHES

The debate is also about differing approaches to product design. Is it better to take an existing product and remove components to make it cheaper, or is it better to simply setup and build a cheap product with all the features you want?

On one side, the Pi Foundation has taken an existing design and removed components from it to make it cheaper. The Pi Zero is a smaller board with less connectors. The CPU is faster by 300MHz than the Raspberry Pi B+, but that is thanks to a software configuration setting, which could be done on the B+ too.

Next Thing Co., on the other hand, only has one computer in their product lineup. C.H.I.P. is inexpensive because NTC has leveraged economies of scale and developed close business relationships with suppliers and manufacturer in Shenzhen, China.

This is how we got here. Six months ago Next Thing Co. launched their $9 computer on Kickstarter, generating over $2 million in pledges. The board is now shipping to crowdfunding backers; they’ll begin taking proper preorders on Cyber Monday.

Meanwhile, on Thursday the Raspberry Pi Foundation announced and began to sell the $5 Pi Zero, and included the board in copies of their MagPi print magazine. It was immediately available, but sold out on all reseller sites by the next day.

Screen Shot 2015-11-25 at 6.35.43 PM

OWNERSHIP COSTS MORE THAN RETAIL PRICE

The cost of owning either a C.H.I.P. or a Pi is a bit more money than the retail cost of the boards. Peripherals such as a power cable, keyboard, mouse, and monitor are necessary to accomplish any computer task on either of the devices. But it turns out the $5 Raspberry Pi Zero costs significantly more to operate than the Next Thing Co. C.H.I.P..

C.H.I.P. Raspberry Pi Zero
Retail Cost $9 $5
Cable Cost $1 USB cable for power $13.35 (USB OTG, USB standard to micro, HDMI to HDMI mini)
Storage Cost None (built-in eMMC storage) $5.65 4GB microSD card
Total Cost $10.00 $24.00
Hardware Specs:
GPIO 80 26 of 40
CPU 1GHz Allwinner R8 1Ghz BCM2835 (same as all pre-Pi 2 boards, but overclocked)
RAM 512MB 512MB
Storage 4GB MicroSD card (not provided)
Wall Power USB 5V @ 300mA (peak) USB 5V
Battery Power Single cell 3.7V LiPo battery w/ 2-pin JST-PH 2.0mm None
WiFi 802.11b/g/n None
BLE Yes None
USB 1 standard & 1 micro with OTG 1 micro with OTG; 1 micro
HDMI No (addon $13 HDMI accessory board is available, cheaper if bought with C.H.I.P.) Yes
Composite Yes via ⅛” mini TRRS to RCA composite video output cable None (hardware hack enabled, requires soldering pins to TV holes)
License Open Hardware Closed
OS Custom Linux, soon to be mainline Linux Custom Linux, not mainline
IO Header type Female headers Through holes
Dimensions 40mm×60mm 65mm×30mm×5mm
Included Cables Composite none

ACTUAL OPERATIONAL COSTS

Regardless of how much it costs to operate a Pi or the fact that you have to buy an add-on board to get HDMI output on C.H.I.P., it’s fantastic that both of these products exist. Even seven months ago, the notion that 1GHz computers would cost under $10 would have seemed a bit crazy. And despite the fact that these boards require additional peripherals to operate in a constructive manner, the price is far less than ever before.

COMMUNITY

And lastly, there’s the community aspect. Raspberry Pi has been around since 2012, with millions of its boards in the wild, huge amounts of established software available, and a large community of users who are available to help with any issues.

C.H.I.P. is the new player in this field, and has created a tremendous buzz with their product. It is leveraging strong relationships in the massive Linux and open source software and hardware communities, which may help it gain a large following. But right now, only crowdfunding backers have their boards. It will take a bit of time for those legs to grow.

What do you think the outcome of these low-cost, powerful devices will be, and what projects do you want to make with them? Be sure to tell us in the comments below.


New SIM800 library aimed at HTTP communication & GSM location

$
0
0

New SIM800 library aimed at HTTP communication & GSM location (Read 1 time)Previous TopicNext Topic

Recently I obtained a cheap (under $8) teeny-tiny SIM800 breakout board. The serial UART interfaced SIM800 makes it very easy for any embedded system to add cellular network access and connect to the cloud.

After some efforts, I managed to make it work with an Arduino Leonardo. Basically 5 wires are needed to connect the module to Arduino and they connect pins of VCC/GND/Rx/Tx/Reset. This is quite straight-forward.

My target is continuously sending HTTP requests containing sensor data to a web server (data as URL argument) and retrieve the response containing command. To make it easier for myself and other people who use the same SIM800 based modules, I started to write an Arduino library for this purpose. It contains only what I need at the moment. That includes what is needed to perform HTTP request and retrieving GSM location data. I am expanding it graudually over the next a few weeks. The library is hosted on GitHub and an exmple sketch is also available. The sketch can be as simple as following.

Code: [Select]

#include "SIM800.h"

#define APN "connect"
#define con Serial
static const char* url = "http://arduinodev.com/datetime.php";

CGPRS_SIM800 gprs;

void setup()
{
con.begin(9600);
while (!con);

for (;;) {
con.print("Resetting...");
while (!gprs.init());
con.println("OK");

con.print("Setting up network...");
byte ret = gprs.setup(APN);
if (ret == 0)
break;
con.print("Error code:");
con.println(ret);
}
con.println("OK");

for (;;) {
if (gprs.httpInit()) break;
con.println(gprs.buffer);
gprs.httpUninit();
delay(1000);
}
}

void loop()
{
gprs.httpConnect(url);
while (gprs.httpIsConnected() == 0) {
// can do something here while waiting
}
if (gprs.httpState == HTTP_ERROR) {
con.println("Connect error");
return;
}
con.println();
gprs.httpRead();
int ret;
while ((ret = gprs.httpIsRead()) == 0) {
// can do something here while waiting
}
if (gprs.httpState == HTTP_ERROR) {
con.println("Read error");
return;
}

// now we have received payload
con.print("[Payload]");
con.println(gprs.buffer);

// show position
GSM_LOCATION loc;
if (gprs.getLocation(&loc)) {
con.print("LAT:");
con.print(loc.lat, 6);
con.print(" LON:");
con.print(loc.lon, 6);
con.print(" TIME:");
con.print(loc.hour);
con.print(':');
con.print(loc.minute);
con.print(':');
con.println(loc.second);
}
}

See here for updates about this library



Raspberry Pi Zero 4 Port USB Hub – Open Source PCB Design

$
0
0

Raspberry Pi Zero 4 Port USB Hub – Open Source PCB Design

pi hub.png

Github link: https://github.com/openhardwarecoza/Rpi-Zero-USB-Hub

In line with my other projects I need to make a USB hub attachment for the Pi Zero.
Seeing as the community figured out that the Raspberry Pi Design team was clever enough to leave us D+  and D- test points at the bottom, I came up with this design above.

See those pads for D+, D-, gnd and 5v?  Yip, the ide is that you can acually reflow this board onto the back of a Pi Zero!

Where’s the Gerbers?  I haven’t uploaded the gerbers to Github yet, since I only finished the Eagle drawing a few mins ago. Eagles are off to DirtyPCBs.com, and once I tested the board, I’ll upload.

This is a 4 Port USB2.0 hub designed around the TI TUSB2046B

  • Directly solderable to Pi Zero USB+PWR pads
  • Cutout for GPIO pin bottoms
  • Screw holes match Pi Zero

BOM:

Part     Value           Package

C2       0.01uF          C0603
C5       15pf            C0603
C6       15pF            C0603
C7       1uF             A/3216-18W
C9       22Pf            C0603
C10      22Pf            C0603
C11      22Pf            C0603
C12      22Pf            C0603
C13      22Pf            C0603
C14      22Pf            C0603
C15      1UF             A/3216-18W
C16      1uF             C/6032-28R
C32      22Pf            C0603
C33      22Pf            C0603
IC5      LD117AS33TR     SOT223
JP1      USB-JST-2MM-SMT S4B-PH
JP3      USB-JST-2MM-SMT S4B-PH
JP5      USB-JST-2MM-SMT S4B-PH
JP8      USB-JST-2MM-SMT S4B-PH
Q2       12MHz           CTS406
R1       15K             R0603
R2       15K             R0603
R3       10k             R0603
R4       22              R0603
R7       22              R0603
R12      15K             R0603
R13      15K             R0603
R14      15K             R0603
R15      15K             R0603
R16      15K             R0603
R17      15K             R0603
R18      15k             R0603
U$5      TUSB2046B     LQFP-32

As always, design’s yours to do as you please, if you do end up getting rich selling these, remember you owe me a few beers (;

If you like the work I do, please consider supporting me by donating to https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=45DXEXK9LJSWU


ENCRYPTION FOR ARDUINO WITH SPRITZ

$
0
0

ENCRYPTION FOR ARDUINO WITH SPRITZ

Hackaday.io user [Abderraouf] has written an implementation of the new(ish) Spritz cipher and hash for Arduino. While we’re not big enough crypto-nerds to assess the security of the code, it looks like it’s going to be pretty handy.

Spritz itself is a neat cipher. Instead of taking in fixed blocks of data and operating on them, it allows you to process it in (almost) whatever chunks it comes in naturally, and then extract out the encrypted results piecewise. It works both as a two-way cipher and as a one-way hash function. It looks like Spritz is a one-stop-shop for all of your encryption needs, and now you can run it on your Arduino.

In case you are afraid of new implementations of new ciphers (and you should be), Spritz’s pedigree should help to put you at ease: it was developed by [Ron Rivest] to be a successor to his RC4 algorithm, and it incorporates a lot of the lessons learned about that algorithm over the past. This doesn’t exclude subtle flaws in the implementation of the library (no offence, [Abderraouf]!) or your work downstream, but at least the underlying algorithm seems to be the real deal.

[Abderraouf] links it in his writeup, but just for completeness, here’s the Spritz paper (PDF). What crypto libraries do you currently use for Arduino or microcontroller projects? We’ve been fans of XXTEA for ages, but more because it’s simple and small than because it’s secure. Spritz may be simple enough to implement easily, and still more secure. Sweet.


Web Authentication Methods Explained

$
0
0

Web Authentication Methods Explained

We are keen on security – recently we have published the Node.js Security Checklist. As a sequel, let’s dive deep into the world of cookies, tokens and other web authentication methods.

We are going to start with the most basic one, the HTTP Basic authentication, continue withcookies and tokens, and finish up with signatures and one-time passwords.

HTTP Basic authentication

HTTP Basic authentication is a method for the client to provide a username and a password when making a request.

This is the simplest possible way to enforce access control as it doesn’t require cookies, sessions or anything else. To use this, the client has to send the Authorization header along with every request it makes. The username and password are not encrypted, but constructed this way:

  • username and password are concatenated into a single string: username:password
  • this string is encoded with Base64
  • the Basic keyword is put before this encoded value

Example for a user named john with password secret:

curl --header "Authorization: Basic am9objpzZWNyZXQ=" my-website.com

The same can be observed in Chrome as well:

Google Chrome basic web authentication method

Implementing it is pretty easy in Node.js as well – the following snippet shows how you can do an Express middleware to do so.

import basicAuth from basic-auth;
function unauthorized(res) {
res.set(WWW-Authenticate, Basic realm=Authorization Required);
return res.send(401);
};
export default function auth(req, res, next) {
const {name, pass} = basicAuth(req) || {};
if (!name || !pass) {
return unauthorized(res);
};
if (name === john && pass === secret) {
return next();
}
return unauthorized(res);
};
view rawbasicAuth.es6 hosted with ❤ by GitHub

Of course, you can do it on a higher level, like in nginx.

Looks simple, right? So what are the drawbacks of using HTTP Basic authentication?

The cons:

  • the username and password are sent with every request, potentially exposing them – even if sent via a secure connection
  • connected to SSL/TLS, if a website uses weak encryption, or an attacker can break it, the usernames and passwords will be exposed immediately
  • there is no way to log out the user using Basic auth
  • expiration of credentials is not trivial – you have to ask the user to change password to do so

Cookies

When a server receives an HTTP request in the response, it can send a Set-Cookie header. The browser puts it into a cookie jar, and the cookie will be sent along with every request made to the same origin in the Cookie HTTP header.

To use cookies for authentication purposes, there are a few key principles that one must follow.

Always use HttpOnly cookies

To mitigate the possibility of XSS attacks always use the HttpOnly flag when setting cookies. This way they won’t show up in document.cookies.

Always use signed cookies

With signed cookies, a server can tell if a cookie was modified by the client.

This can be observed in Chrome as well – first let’s take a look at how a server set cookies:

illustration of Chrome cookie set for web authentication purposes

Later on all the requests use the cookies set for the given domain:

web authentication method illustration Chrome cookie usage


The cons:

  • Need to make extra effort to mitigate CSRF attacks
  • Incompatibility with REST – as it introduces a state into a stateless protocol

Tokens

Nowadays JWT (JSON Web Token) is everywhere – still it is worth taking a look on potential security issues.

First let’s see what JWT is!

JWT consists of three parts:

  • Header, containing the type of the token and the hashing algorithm
  • Payload, containing the claims
  • Signature, which can be calculated as follows if you chose HMAC SHA256: HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

Adding JWT to Koa applications is only a couple of lines of code:

var koa = require(koa);
var jwt = require(koa-jwt);
var app = koa();
app.use(jwt({
secret: very-secret
}));
// Protected middleware
app.use(function *(){
// content of the token will be available on this.state.user
this.body = {
secret: 42
};
});
view rawserver.js hosted with ❤ by GitHub

Example usage – (to check out the validity/content of the token, you can use jwt.io):

curl --header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ" my-website.com

As the previous ones, the tokens can be observed in Chrome as well:

Google Chrome JSON Web Token as a web authentication method

If you are writing APIs for native mobile applications or SPAs, JWT can be a good fit. One thing to keep in mind: to use JWT in the browser you have to store it in either LocalStorage or SessionStorage, which can lead to XSS attacks.

The cons:

Signatures

Either using cookies or tokens, if the transport layer for whatever reason gets exposed your credentials are easy to access – and with a token or cookie the attacker can act like the real user.

A possible way to solve this – at least when we are talking about APIs and not the browser is to sign each request. How does that work?

When a consumer of an API makes a request it has to sign it, meaning it has to create a hash from the entire request using a private key. For that hash calculation you may use:

  • HTTP method
  • Path of the request
  • HTTP headers
  • Checksum of the HTTP payload
  • and a private key to create the hash

To make it work, both the consumer of the API and the provider have to have the same private key. Once you have the signature, you have to add it to the request, either in query strings or HTTP headers. Also, a date should be added as well, so you can define an expiration date.

AWS Request Signing: Flow of a Web Authentication MethodAWS Request Signing Flow – source

Why go through all these steps? Because even if the transport layer gets compromised, an attacker can only read your traffic, won’t be able to act as a user, as the attacker will not be able to sign requests – as the private key is not in his/her possession. Most AWS services are using this kind of authentication.

node-http-signature deals with HTTP Request Signing and worth checking out.

The cons:

  • cannot use in the browser / client, only between APIs

One-Time Passwords

One-Time passwords algorithms generate a one-time password with a shared secret and either the current time or a counter:

  • Time-based One-time Password Algorithm, based on the current time,
  • HMAC-based One-time Password Algorithm, based on a counter.

These methods are used in applications that leverage two-factor authentication: a user enters the username and password then both the server and the client generates a one-time password.

In Node.js, implementing this using notp is relatively easy.

Cons:

  • with the shared-secret (if stolen) user tokens can be emulated
  • because clients can be stolen / go wrong every real-time application have methods to bypass this, like an email reset that adds additional attack vectors to the application

Which web authentication method to pick when?

If you have to support a web application only, either cookies or tokens are fine – for cookies think about XSRF, for JWT take care of XSS.

If you have to support both a web application and a mobile client, go with an API that supports token-based authentication.

If you are building APIs that communicate with each other, go with request signing.

You have additional thoughts or insights on the topic? Share it in the comments.


How to run a Pi Zero (and other Pi’s) from a LiPo Including low battery @Raspberry_Pi #piday #raspberypi

$
0
0

How to run a Pi Zero (and other Pi’s) from a LiPo Including low battery @Raspberry_Pi #piday #raspberypi

Wiring

Super useful hack from Daniel Bull posted on Google Plus, via raspberrypipod.

Including low battery automatic shutdown (to stop your SD card from getting corrupted), push button start, and automatic power supply off when the Pi is shutdown to stop your LiPo from going flat.

I’ve included full instructions on how to do this including circuit diagrams here:
https://github.com/NeonHorizon/lipopi

Read more.


Featured Adafruit Products!

1944 00

PowerBoost 500 Charger – Rechargeable 5V Lipo USB Boost @ 500mA+: PowerBoost 500C is the perfect power supply for your portable project! With a built-in battery charger circuit, you’ll be able to keep your project running even while recharging the battery! This little DC/DC boost converter module can be powered by any 3.7V LiIon/LiPoly battery, and convert the battery output to 5.2V DC for running your 5V projects. (read more)


DES algorithm on Arduino

$
0
0

DES algorithm

Here is the arduino DES algorithm which implements a full DES encryption and decoding.
You can set the key and use any plaintext  and cipher text and take the algorithm any way you want.
It is very visual in that every step prints to screen all the details so you can see how it works. This way you will quickly grasp the DES algorithm.
You can find the arduino DES algorithm code to download in my example below which is based on the Daniel Otte version (See link below). If you want to see the detailed steps of how a DES algorithm is built up you can look at this page describing the data encryption standard.
Click on the link below to see what the program looks like on the page.

Hide «

/*

 * Title  DES algorithm for the Data Encryption Standard implementation
 * based on DES algorithm by  Daniel Ottee  email daniel.otte@rub.de 
 * date     14-02-2012
 */
#include <stdint.h>
#include <string.h>

const uint8_t sbox[256]  = {
  /* S-box 1 */
  0xE4, 0xD1, 0x2F, 0xB8, 0x3A, 0x6C, 0x59, 0x07,
  0x0F, 0x74, 0xE2, 0xD1, 0xA6, 0xCB, 0x95, 0x38,
  0x41, 0xE8, 0xD6, 0x2B, 0xFC, 0x97, 0x3A, 0x50,
  0xFC, 0x82, 0x49, 0x17, 0x5B, 0x3E, 0xA0, 0x6D,
  /* S-box 2 */
  0xF1, 0x8E, 0x6B, 0x34, 0x97, 0x2D, 0xC0, 0x5A,
  0x3D, 0x47, 0xF2, 0x8E, 0xC0, 0x1A, 0x69, 0xB5,
  0x0E, 0x7B, 0xA4, 0xD1, 0x58, 0xC6, 0x93, 0x2F,
  0xD8, 0xA1, 0x3F, 0x42, 0xB6, 0x7C, 0x05, 0xE9,
  /* S-box 3 */
  0xA0, 0x9E, 0x63, 0xF5, 0x1D, 0xC7, 0xB4, 0x28,
  0xD7, 0x09, 0x34, 0x6A, 0x28, 0x5E, 0xCB, 0xF1,
  0xD6, 0x49, 0x8F, 0x30, 0xB1, 0x2C, 0x5A, 0xE7,
  0x1A, 0xD0, 0x69, 0x87, 0x4F, 0xE3, 0xB5, 0x2C,
  /* S-box 4 */
  0x7D, 0xE3, 0x06, 0x9A, 0x12, 0x85, 0xBC, 0x4F,
  0xD8, 0xB5, 0x6F, 0x03, 0x47, 0x2C, 0x1A, 0xE9,
  0xA6, 0x90, 0xCB, 0x7D, 0xF1, 0x3E, 0x52, 0x84,
  0x3F, 0x06, 0xA1, 0xD8, 0x94, 0x5B, 0xC7, 0x2E,
  /* S-box 5 */
  0x2C, 0x41, 0x7A, 0xB6, 0x85, 0x3F, 0xD0, 0xE9,
  0xEB, 0x2C, 0x47, 0xD1, 0x50, 0xFA, 0x39, 0x86,
  0x42, 0x1B, 0xAD, 0x78, 0xF9, 0xC5, 0x63, 0x0E,
  0xB8, 0xC7, 0x1E, 0x2D, 0x6F, 0x09, 0xA4, 0x53,
  /* S-box 6 */
  0xC1, 0xAF, 0x92, 0x68, 0x0D, 0x34, 0xE7, 0x5B,
  0xAF, 0x42, 0x7C, 0x95, 0x61, 0xDE, 0x0B, 0x38,
  0x9E, 0xF5, 0x28, 0xC3, 0x70, 0x4A, 0x1D, 0xB6,
  0x43, 0x2C, 0x95, 0xFA, 0xBE, 0x17, 0x60, 0x8D,
  /* S-box 7 */
  0x4B, 0x2E, 0xF0, 0x8D, 0x3C, 0x97, 0x5A, 0x61,
  0xD0, 0xB7, 0x49, 0x1A, 0xE3, 0x5C, 0x2F, 0x86,
  0x14, 0xBD, 0xC3, 0x7E, 0xAF, 0x68, 0x05, 0x92,
  0x6B, 0xD8, 0x14, 0xA7, 0x95, 0x0F, 0xE2, 0x3C,
  /* S-box 8 */
  0xD2, 0x84, 0x6F, 0xB1, 0xA9, 0x3E, 0x50, 0xC7,
  0x1F, 0xD8, 0xA3, 0x74, 0xC5, 0x6B, 0x0E, 0x92,
  0x7B, 0x41, 0x9C, 0xE2, 0x06, 0xAD, 0xF3, 0x58,
  0x21, 0xE7, 0x4A, 0x8D, 0xFC, 0x90, 0x35, 0x6B
};

const uint8_t e_permtab[] ={
	 4,  6, 					/* 4 bytes in 6 bytes out*/
	32,  1,  2,  3,  4,  5,
	 4,  5,  6,  7,  8,  9,
	 8,  9, 10, 11, 12, 13,
	12, 13, 14, 15, 16, 17,
	16, 17, 18, 19, 20, 21,
	20, 21, 22, 23, 24, 25,
	24, 25, 26, 27, 28, 29,
	28, 29, 30, 31, 32,  1
};

const uint8_t p_permtab[] ={
	 4,  4,						/* 32 bit -> 32 bit */
	16,  7, 20, 21,
	29, 12, 28, 17,
	 1, 15, 23, 26,
	 5, 18, 31, 10,
	 2,  8, 24, 14,
	32, 27,  3,  9,
	19, 13, 30,  6,
	22, 11,  4, 25
};

const uint8_t ip_permtab[] ={
	 8,  8,						/* 64 bit -> 64 bit */
	58, 50, 42, 34, 26, 18, 10, 2,
	60, 52, 44, 36, 28, 20, 12, 4,
	62, 54, 46, 38, 30, 22, 14, 6,
	64, 56, 48, 40, 32, 24, 16, 8,
	57, 49, 41, 33, 25, 17,  9, 1,
	59, 51, 43, 35, 27, 19, 11, 3,
	61, 53, 45, 37, 29, 21, 13, 5,
	63, 55, 47, 39, 31, 23, 15, 7
};

const uint8_t inv_ip_permtab[] ={
	 8, 8,						/* 64 bit -> 64 bit */
	40, 8, 48, 16, 56, 24, 64, 32,
	39, 7, 47, 15, 55, 23, 63, 31,
	38, 6, 46, 14, 54, 22, 62, 30,
	37, 5, 45, 13, 53, 21, 61, 29,
	36, 4, 44, 12, 52, 20, 60, 28,
	35, 3, 43, 11, 51, 19, 59, 27,
	34, 2, 42, 10, 50, 18, 58, 26,
	33, 1, 41,  9, 49, 17, 57, 25
};

const uint8_t pc1_permtab[] ={
	 8,  7, 					/* 64 bit -> 56 bit*/
	57, 49, 41, 33, 25, 17,  9,
	 1, 58, 50, 42, 34, 26, 18,
	10,  2, 59, 51, 43, 35, 27,
	19, 11,  3, 60, 52, 44, 36,
	63, 55, 47, 39, 31, 23, 15,
	 7, 62, 54, 46, 38, 30, 22,
	14,  6, 61, 53, 45, 37, 29,
	21, 13,  5, 28, 20, 12,  4
};

const uint8_t pc2_permtab[] ={
	 7,	 6, 					/* 56 bit -> 48 bit */
	14, 17, 11, 24,  1,  5,
	 3, 28, 15,  6, 21, 10,
	23, 19, 12,  4, 26,  8,
	16,  7, 27, 20, 13,  2,
	41, 52, 31, 37, 47, 55,
	30, 40, 51, 45, 33, 48,
	44, 49, 39, 56, 34, 53,
	46, 42, 50, 36, 29, 32
};

const uint8_t splitin6bitword_permtab[] = {
	 8,  8, 					/* 64 bit -> 64 bit */
	64, 64,  1,  6,  2,  3,  4,  5, 
	64, 64,  7, 12,  8,  9, 10, 11, 
	64, 64, 13, 18, 14, 15, 16, 17, 
	64, 64, 19, 24, 20, 21, 22, 23, 
	64, 64, 25, 30, 26, 27, 28, 29, 
	64, 64, 31, 36, 32, 33, 34, 35, 
	64, 64, 37, 42, 38, 39, 40, 41, 
	64, 64, 43, 48, 44, 45, 46, 47 
};

const uint8_t shiftkey_permtab[] = {
	 7,  7, 					/* 56 bit -> 56 bit */
	 2,  3,  4,  5,  6,  7,  8,  9,
	10, 11, 12, 13, 14, 15, 16, 17,
	18, 19, 20, 21, 22, 23, 24, 25, 
	26, 27, 28,  1, 
	30, 31, 32, 33, 34, 35, 36, 37, 
	38, 39, 40, 41, 42, 43, 44, 45, 
	46, 47, 48, 49, 50, 51, 52, 53, 
	54, 55, 56, 29
};

/*
1 2 2 2   2 2 2 1   2 2 2 2   2 2 1 1
0 1 1 1   1 1 1 0   1 1 1 1   1 1 0 0
      7         E         F         C    Standard DES
2 1 1 1   1 1 1 1   2 2 1 1   1 2 1 1
1 0 0 0   0 0 0 0   1 1 0 0   0 1 0 0
      8         0         C         4    Meteotime DES
*/
#define ROTTABLE      0x7EFC 
byte crypt [8];
byte plaintext [] = { 00,01,02,03,04,05,06,07};
byte keyword [] = { 0x3b,0x38,0x98,0x37,0x15,0x20,0xf7,0x5e};
byte test[8];
boolean DEBUG = true;
int i,m;
int Dx =0;
uint32_t box=0,t;
String showprint = "";
uint8_t data[8];
/******************************************************************************/
void setup(){

Serial.begin(19200);
Serial.println("Start");
Serial.print ("Keyword       = ");
for (int j=0;j<8;j++){
if (keyword[j]<0x10) Serial.print("0"); 
Serial.print(keyword[j],HEX);Serial.print(" ");
}
Serial.println();
Serial.print ("Plaintext     = ");
for (int j=0;j<8;j++){
if (plaintext[j]<0x10) Serial.print("0"); 
Serial.print(plaintext[j],HEX);Serial.print(" ");
}
Serial.println();
Serial.println("Encrypting");
//void des_enc(void* out, const void* in, const void* key);
des_enc( crypt, plaintext, keyword);
Serial.print("Encrypted key  = ");
for (int j=0;j<8;j++){
if (crypt[j]<0x10) Serial.print("0"); 
Serial.print(crypt[j],HEX);Serial.print(" ");
}
Serial.println();
Serial.println("Decrypting");
//void des_dec(void* out, const void* in, const void* key);
des_dec( plaintext, crypt, keyword);
Serial.print("Decrypted key  = ");
for (int j=0;j<8;j++){
if (plaintext[j]<0x10) Serial.print("0"); 
Serial.print(plaintext[j],HEX);Serial.print(" ");
}
Serial.println();
Serial.println("Done");
}

void loop(){
}

void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){
	uint8_t ob; /* in-bytes and out-bytes */
	uint8_t byte, bit; /* counter for bit and byte */
	ob = ptable[1];
	ptable = &(ptable[2]);
	for(byte=0; byte<ob; ++byte){
		uint8_t x,t=0;
		for(bit=0; bit<8; ++bit){
			x=*ptable++ -1 ;
				t<<=1;
			if((inyes) & (0x80>>(x%8)) ){
				t|=0x01;
			}
		}
		out[byte]=t;test[byte]=t;
	}
}

/******************************************************************************/

void changeendian32(uint32_t * a){
	*a = (*a & 0x000000FF) << 24 |
		 (*a & 0x0000FF00) <<  8 |
		 (*a & 0x00FF0000) >>  8 |
		 (*a & 0xFF000000) >> 24;
box=((*a & 0x000000FF) << 24)|
		 (*a & 0x0000FF00) <<  8 |
		 (*a & 0x00FF0000) >>  8 |
		 (*a & 0xFF000000) >> 24;
}

/******************************************************************************/
static inline
void shiftkey(uint8_t *key){
	uint8_t k[7];
	memcpy(k, key, 7);
	permute((uint8_t*)shiftkey_permtab, k, key);
        if (DEBUG == true) {
        Serial.print ("CD[");Serial.print(m);Serial.print ("]  56 xits = ");
        for (int j=0;j<7;j++){
        if (test[j]<0x10) Serial.print("0"); 
        Serial.print(test[j],HEX);Serial.print(" ");
        print_binary(test[j],8);Serial.print(" ");
        }
        Serial.println();
        }
}

/******************************************************************************/

/******************************************************************************/
static inline
uint64_t splitin6bitwords(uint64_t a){
	uint64_t ret=0;
	a &= 0x0000ffffffffffffLL;
	permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret);
	return ret;
}

/******************************************************************************/

static inline
uint8_t substitute(uint8_t a, uint8_t * sbp){
	uint8_t x;
	x = sbp[a>>1];
	x = (a&1)?x&0x0F:x>>4;
	return x;

}

/******************************************************************************/

uint32_t des_f(uint32_t r, uint8_t* kr){
	uint8_t i;
	uint32_t ret;
	uint64_t data;
	uint8_t *sbp; /* sboxpointer */ 
	permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data);
        showprint ="E      48 bits = ";printout1(0,6);
	for(i=0; i<7; ++i) {((uint8_t*)&data)[i] ^= kr[i];}
        if (DEBUG == true) {
        Serial.print ("ExorKS 48 bits = ");
        for (int j=0;j<6;j++){
        if (((uint8_t*)&data)[j]<0x10) Serial.print("0"); 
        Serial.print(((uint8_t*)&data)[j],HEX);Serial.print(" ");
        print_binary(((uint8_t*)&data)[j],8);Serial.print(" ");
        }
        Serial.println();
        }

	/* Sbox substitution */
	data = splitin6bitwords(data);
	sbp=(uint8_t*)sbox;
	for(i=0; i<8; ++i){
		uint8_t x;
		x = substitute(((uint8_t*)&data)[i], sbp);
		t<<=4;
		t |= x;
		sbp += 32;
	}
	changeendian32(&t);
        if (DEBUG == true) { 
        Serial.print ("Sbox   32 bits = ");

        if (box/0x1000000<0x10) Serial.print("0"); 
        Serial.print(box/0x1000000,HEX);Serial.print(" ");
        print_binary(box/0x1000000,8);Serial.print(" ");

        if (box/0x10000&0xFF<0x10) Serial.print("0"); 
        Serial.print(box/0x10000&0xFF,HEX);Serial.print(" ");
        print_binary(box/0x10000&0xFF,8);Serial.print(" "); 

        if (((box/0x100)&0xFF)<0x10) Serial.print("0"); 
        Serial.print(box/0x100&0xFF,HEX);Serial.print(" ");        
        print_binary(box/0x100,8);Serial.print(" ");

        if (box&0xFF<0x10) Serial.print("0"); 
        Serial.print(box&0xFF,HEX);Serial.print(" ");        
        print_binary(box&0xFF,8);        
        Serial.println();
        }
	permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret);
        showprint = "P      32 bits = "; printout1(0,4); 
	return ret;
}

/******************************************************************************/

void des_enc(void* out, const void* in, const void* key){
#define R *((uint32_t*)&(data[4]))
#define L *((uint32_t*)&(data[0]))
	uint8_t kr[6],k[7];
	permute((uint8_t*)ip_permtab, (uint8_t*)in, data); 
        showprint = "L[0]   32 bits = "; printout1(0,4);
        showprint = "R[0]   32 bits = "; printout1(4,8);
	permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
        showprint = "CD[0]  56 bits = "; printout1(0,7);
	for(i=0; i<8; i++){

                Dx=i*2+1;
                if (DEBUG == true) { Serial.print("Round ");Serial.println(Dx); }
		shiftkey(k);
		if(ROTTABLE&((1<<((i<<1)+0))) ) shiftkey(k);
		permute((uint8_t*)pc2_permtab, k, kr);     
                showprint = "KS     48 bits = "; printout1(0,6);
		L ^= des_f(R, kr);
                showprint = "L[i]   32 bits = "; printout2(0,4);
                showprint = "R[i]   32 bits = "; printout2(4,8);

                Dx=i*2+2;
                if (DEBUG == true) { Serial.print("Round ");Serial.println(Dx); }              
		shiftkey(k);
		if(ROTTABLE&((1<<((i<<1)+1))) ) shiftkey(k);
		permute((uint8_t*)pc2_permtab, k, kr);
                showprint = "KS     48 bits = "; printout1(0,6);
		R ^= des_f(L, kr);
                showprint = "L[i]   32 bits = "; printout2(0,4);
                showprint = "R[i]   32 bits = "; printout2(4,8);
	}
	/* L <-> R*/
	R ^= L;
	L ^= R;
	R ^= L;
        showprint = "LR[16] 64 bits = "; printout2(0,8);
	permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out);
        showprint = "Crypt  64 bits = "; printout1(0,8);
}

/******************************************************************************/

void des_dec(void* out, const void* in, const uint8_t* key){
#define R *((uint32_t*)&(data[4]))
#define L *((uint32_t*)&(data[0]))
	uint8_t kr[6],k[7];
        Serial.print("crypt  64 bits = ");
        for (int j=0;j<8;j++){
        if (crypt[j]<0x10) Serial.print("0"); 
        Serial.print(crypt[j],HEX);Serial.print(" ");
        print_binary(crypt[j],8);Serial.print(" ");
        }
        Serial.println();
        Serial.print("key    64 bits = ");
        for (int j=0;j<8;j++){
        if (key[j]<0x10) Serial.print("0"); 
        Serial.print(key[j],HEX);Serial.print(" ");
        print_binary(key[j],8);Serial.print(" ");
        }
        Serial.println();        
	permute((uint8_t*)ip_permtab, (uint8_t*)in, data);
        showprint = "L[0]   32 bits = "; printout1(0,4);
        showprint = "R[0]   32 bits = "; printout1(4,8);
	permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
        showprint = "CD[0]  56 bits = "; printout1(0,7);
	for(i=7; i>=0; i--){

                Dx=i*2+2;
                if (DEBUG == true) { Serial.print("Round ");Serial.println(Dx); }
                permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
                for (m=1;m<Dx+1;m++){ 
                shiftkey(k);
                if(ROTTABLE&(1<<(m-1))) shiftkey(k);
                }              
		permute((uint8_t*)pc2_permtab, k, kr);
                showprint = "KS     48 bits = "; printout1(0,6);
		L ^= des_f(R, kr);
                showprint = "L[i]   32 bits = "; printout2(0,4);
                showprint = "R[i]   32 bits = "; printout2(4,8);

                Dx=i*2+1;
                if (DEBUG == true) { Serial.print("Round ");Serial.println(Dx); } 
                permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
                for (m=1;m<Dx+1;m++){  
 		shiftkey(k);
                if(ROTTABLE&(1<<(m-1))) shiftkey(k); 
                }              
		permute((uint8_t*)pc2_permtab, k, kr);
                showprint = "KS     48 bits = "; printout1(0,6);
		R ^= des_f(L, kr);
                showprint = "L[i]   32 bits = "; printout2(0,4);
                showprint = "R[i]   32 bits = "; printout2(4,8);
	}
	/* L <-> R*/
	R ^= L;
	L ^= R;
	R ^= L;
        showprint = "LR[16] 64 bits = "; printout2(0,8);
	permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out);
        showprint = "Plain  64 bits = "; printout1(0,8);
}
void print_binary(uint64_t v, int num_places)
{
    uint64_t mask=0, n;
    for (n=1; n<=num_places; n++)
    {
        mask = (mask << 1) | 0x00000001;
    }
    v = v & mask;  // truncate v to specified number of places
    while(num_places)
    {
        if (v & (0x00000001 << num_places-1))
        {
             Serial.print("1");
        }
        else
        {
             Serial.print("0");
        }
        --num_places;
        if(((num_places%8) == 0) && (num_places != 0))
        {
            Serial.print(" ");
        }

    }
}
void printout1(int min,int max) {
        if (DEBUG == true) {
        Serial.print (showprint);
        for (int j=min;j<max;j++){
        if (test[j]<0x10) Serial.print("0");
        Serial.print(test[j],HEX);Serial.print(" ");
        print_binary(test[j],8);Serial.print(" ");
        }
        Serial.println();
        }
}
void printout2(int min,int max) {
        if (DEBUG == true) {
        Serial.print (showprint);
        for (int j=min;j<max;j++){
        if (data[j]<0x10) Serial.print("0");
        Serial.print(data[j],HEX);Serial.print(" ");
        print_binary(data[j],8);Serial.print(" ");
        }
        Serial.println();
        }
}

Other DES algorithm related stuff:

There are other encryption techniques such as AES etc used which can be seen here.
http://www.efgh.com/software/des.htm
http://dvd-copy-software-review.toptenreviews.com/the-dos-and-donts-of-decryption.html
There is a very good excel version of such a process which visualizes the whole process that can be downloaded from the bottom of the link above.
Other version non arduino of the DES algorithm by Daniel Otte.

Here you can find my other arduino projects.


Viewing all 764 articles
Browse latest View live