<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Jayson DeLancey on Medium]]></title>
        <description><![CDATA[Stories by Jayson DeLancey on Medium]]></description>
        <link>https://medium.com/@j12y?source=rss-f3c028e6e549------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*GK4LtZ-EzjTlgSUIeD7CMw.jpeg</url>
            <title>Stories by Jayson DeLancey on Medium</title>
            <link>https://medium.com/@j12y?source=rss-f3c028e6e549------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 07 Apr 2026 14:52:03 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@j12y/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[A Location Based TODO App]]></title>
            <link>https://j12y.medium.com/a-location-based-todo-app-a6cf3ecc096a?source=rss-f3c028e6e549------2</link>
            <guid isPermaLink="false">https://medium.com/p/a6cf3ecc096a</guid>
            <category><![CDATA[maps]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Jayson DeLancey]]></dc:creator>
            <pubDate>Wed, 30 Dec 2020 19:40:55 GMT</pubDate>
            <atom:updated>2023-03-05T17:49:27.151Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/797/1*fnz0qTZRzgc39v7AK59kJg.png" /></figure><p>I want to use a TODO application that takes into account where I need to be to complete a task. I don’t “buy milk” while at home nor do I “cut the grass” when I’m at work. I want my TODO application to be smart and only show me tasks that make sense for where I am or where I’m going.</p><h3>TodoMVC</h3><p>If you are unfamiliar with <a href="https://github.com/tastejs/todomvc">TodoMVC</a>, it was started by Addy Osmani and Sindre Sorhus sometime around 2012 with the help of many <a href="https://github.com/tastejs/todomvc/graphs/contributors">contributors</a> over the years as “a project which offers the same Todo application implemented in most of the popular JavaScript MV* frameworks of today — think of it as speed dating for frameworks.” (<a href="https://www.smashingmagazine.com/2012/07/journey-through-the-javascript-mvc-jungle/">1</a>)</p><p>With the TodoMVC React implementation as a starting point we’re going to start adding location features.</p><ul><li>[ ] Add latitude and longitude with a TODO React component</li><li>[ ] Display TODOs with a marker on a Map component</li></ul><p>Additionally, there is a little bit of housekeeping to update the sample with the latest ES6 and React functionality.</p><h3>// TODO: Run “Hello World”</h3><p>There are at least two paths for getting a “Hello World” started quickly.</p><p>If you are more of a deconstructionist that wants to start with a working app and take it apart to understand how it works:</p><pre>git clone <a href="https://github.com/tastejs/todomvc.git">https://github.com/tastejs/todomvc.git</a><br>cd todomvc<br>python -m SimpleHTTPServer</pre><p>You should be able to view <a href="http://localhost:8000">http://localhost:8000</a> and navigate to the React example found in examples/react. If you are more of a constructionist and want to start with a blank slate and build up by adding piece by piece:</p><pre>npx create-react-app my-todo-app<br>cd my-todo-app<br>npm start</pre><p>I prefer this approach, so when <a href="https://reactjs.org/docs/create-a-new-react-app.html#create-react-app">create-react-app</a> finishes you should be able to view <a href="http://localhost:3000">http://localhost:3000</a> with live reloading and a basic Hello World React App.</p><h3>// TODO: Add A Component</h3><p>A React component is a structure for creating independent, reusable pieces of a user interface. The component accepts properties as input and returns a React element that can be rendered.</p><p>TodoMVC originated with a goal of implementing an architecture by which the **M**odel, **V**iew, and **C**ontroller were independent. React aims to not artificially separate technologies such as JavaScript from HTML/CSS but rather separate concerns with loosely coupled components that contain both. The Reactjs.org [Main Concepts](<a href="https://reactjs.org/docs/components-and-props.html">https://reactjs.org/docs/components-and-props.html</a>) goes into more detail on this design approach.</p><p>Review the following component source. It defines a simple text input box that defaults to the current location. There are inline comments to help describe some of the logic.</p><pre>import React, { Component } from &#39;react&#39;;</pre><pre>// This class definition is a React.Component so that we<br>// can use it in multiple places for the app.</pre><pre>class Location extends Component {</pre><pre>// The constructor takes properties defined as element attributes<br>  // defined in JSX along with an initial default value for state.</pre><pre>constructor(props) {<br>    super(props);<br>    this.state = {<br>      value: &#39;0,0&#39;, // Null Island<br>      error: null,<br>    }<br>  }</pre><pre>// When the component is rendered to the DOM for the first time<br>  // such as at page load we call the Geolocation API to determine<br>  // a latitude and longitude for the browser</pre><pre>componentDidMount() {<br>    if (navigator.geolocation) {<br>      navigator.geolocation.getCurrentPosition(<br>        (position) =&gt; {<br>          this.setState({<br>            value: position.coords.latitude + &#39;,&#39; + position.coords.longitude,<br>            error: null,<br>          });<br>        },<br>        (error) =&gt; this.setState(<br>          {error: error.message}<br>        )<br>      );<br>    }<br>  }</pre><pre>// Respond to user input with event callback<br>  <br>changeLocation(evt) {<br>    this.setState({<br>        value: evt.target.value,<br>      }<br>    )<br>  }</pre><pre>// The JSX definition for how to render this component on the page.  <br>  // In this case, it&#39;s a simple input field for new todo items.</pre><pre>render() {<br>    return (<br>            &lt;input<br>              className=&quot;new-todo&quot;<br>              value={ this.state.value }<br>              onChange={ evt =&gt; this.changeLocation(evt) }<br>              /&gt;<br>    );<br>  }<br>}</pre><h3>// TODO: Add a Map</h3><p>For the map, we’re going to use the <a href="https://developer.here.com/documentation/map-image/topics/quick-start-show-default-location.html">Map Image API</a> which provides a quick and easy way to fetch a static image. The parameters take some getting used to but let me unpack the basics here:</p><ul><li>w=600 specifies the width of the image tile requested and h=300 the height</li><li>z=10 specifies the zoom level</li><li>t=5 specifies the rendering scheme so you can choose from various styles of map tiles including satellite, transit, etc.</li><li>poitxs=1 , poitxc=black , and poitfc=yellow specifies the point of interest size, background color, and foreground color</li><li>app_idd=... and app_code=... are found in the here developer projects section and needed for working with any HERE APIs.</li></ul><p>Each of these parameters could be stored as either props or state on the component to provide rich customization options to users. The last parameter we want to send to the Map Image API is the poi= for a comma separated list of latitude and longitude for any markers we want to place.</p><p>In the case of my TODO app, I’ve added two tasks with locations:</p><ul><li>“Return Library Book” at 37.86836, -122.26859</li><li>“Pickup Badge for TechCrunch” at 37.784117,-122.401386</li></ul><p>The poi query we’d want to make for these todo items would look like poi=37.86836,-122.26859,37.784117,-122.401386.</p><p>Here is an example of the Map component that will re-render with each setState() call when adding points of interest:</p><pre>class Map extends Component {</pre><pre>// For conciseness simply included all parameters in the querystring directly</pre><pre>constructor(props) {<br>    super(props);<br>    this.state = {<br>      url: &#39;<a href="https://image.maps.api.here.com/mia/1.6/mapview?w=600&amp;h=300&amp;z=10&amp;t=5&amp;poitxs=16&amp;poitxc=black&amp;poifc=yellow&#39;">https://image.maps.api.here.com/mia/1.6/mapview?w=600&amp;h=300&amp;z=10&amp;t=5&amp;poitxs=16&amp;poitxc=black&amp;poifc=yellow&#39;</a>,<br>      points: [],<br>    }<br>  }</pre><pre>// Helper function to format list of points</pre><pre>getPOIList() {<br>    if (this.state.points.length &gt; 0) {<br>      let param = &#39;&amp;poi=&#39;;<br>      for (var poi in this.state.points) {<br>        param += poi.latitude + &#39;,&#39; + poi.longitude;<br>      }<br>      return param;<br>    }</pre><pre>return &#39;&#39;;<br>  }</pre><pre>// Render method builds the URL dynamically to fetch the image from the<br>  // HERE Map Image API</pre><pre>render() {<br>    return (<br>      &lt;img<br>        src={ this.state.url<br>          + &#39;&amp;app_id=&#39; + this.props.app_id<br>          + &#39;&amp;app_code=&#39; + this.props.app_code<br>          + this.getPOIList()<br>          }<br>        alt=&quot;Todo Map&quot;/&gt;<br>    );<br>  }<br>}</pre><p>Once defined, you can reuse this component in any other component such as the root app component.</p><pre>&lt;Map app_id=”PUT_APP_ID_HERE” app_code=”PUT_APP_CODE_HERE” /&gt;</pre><h3>// TODO: Wrap It Up</h3><p>This first post introduced TodoMVC with a couple of very basic React components that leverage the HERE Map Image API. In upcoming React posts I’ll dive deeper into this example to respond to state changes with event handling for geocoding lookups, map clustering for TODOs at the nearby locations with conditional rendering, Matrix Routing to get between TODO locations efficiently, Place Search to find related TODO items, and a few other project integrations to polish up the final todo app.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a6cf3ecc096a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How I Became a Youth Ice Hockey Videographer]]></title>
            <link>https://j12y.medium.com/how-i-became-a-youth-ice-hockey-videographer-2a4901ce45db?source=rss-f3c028e6e549------2</link>
            <guid isPermaLink="false">https://medium.com/p/2a4901ce45db</guid>
            <category><![CDATA[sports]]></category>
            <dc:creator><![CDATA[Jayson DeLancey]]></dc:creator>
            <pubDate>Sat, 05 Oct 2019 23:46:20 GMT</pubDate>
            <atom:updated>2019-10-05T23:56:51.608Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4eoiSbNOc-UOdw440gefAg.png" /></figure><p>I suspect it is not uncommon for somebody technically minded to volunteer to do something only to find themselves realizing, “ok, well, now I need to figure out how to do that” simply because they were looking for a challenge. I decided to start recording video from my son’s ice hockey games as the team videographer. I have no prior experience doing any video editing or filming of anything let alone sports, but professionally I do know how to write software even if I’m an amateur when it comes to media.</p><p>What I have observed is that parents like to be able to see their son or daughter score a goal or make a key save. Coaches like to review video and find teachable moments and lessons on teamwork. Individual players want to perform at higher and higher levels on their way to their dreams of the NHL so want to review video just like the pros to refine their own techniques and results.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TEcRZSuu9Fe0YXILN0v_0A.gif" /><figcaption>“Get in the fast lane grandma, the bingo game’s ready to roll!” — Mike Lange</figcaption></figure><p>My goal is not to become a professional video editor or sports analyst. I want to help the parents, coaches, and players get what they want but without spending all of my free time doing it. I want to automate, hack and take short-cuts, derive insights and still come out with something useful and professional looking with as little effort as is necessary. Larry Wall, creator of the Perl programming language, defined the <a href="http://threevirtues.com/">Three Virtues</a> of a great programmer which includes <strong>laziness,</strong> a quality that makes you go through great lengths to not do work later by spending even more energy up front writing programs to save labor in the long run.</p><p>There are challenges and solutions which I’ll be releasing over the course of the 2019–2020 PeeWee (12 and under) season. Broadly these lessons fall into the categories of:</p><ul><li>Capture — the decisions for equipment needed to capture raw audio and video from multiple locations</li><li>Editing — telling the story of the event when not everything captured is useful or re-assembled from various perspectives</li><li>Storage — planning for storing and archiving media</li><li>Analysis — identifying what happened and when through a combination of video and audio analysis combined with scoresheets</li><li>Delivery — how to get the results efficiently to the audience and stakeholders</li></ul><p>While I’m part of an ice hockey family, there are similar communities that can benefit from similar approaches with football, soccer, baseball, lacrosse, etc.</p><p>The pre-season has wrapped up so now it’s time to put it all in practice. The questions I’ll be answering include:</p><ul><li>What equipment should I use to capture ice hockey footage?</li><li>What are the ideal settings in terms of quality and frames per second?</li><li>How to get the data from multiple camera sources loaded?</li><li>How to manage local or cloud media file storage?</li><li>Which settings and codecs can I use to transcode for efficient use of space and quality?</li><li>How to synchronize multiple video feeds in a timeline?</li><li>What can I do to improve the audio of the media to sound more like sports broadcasts?</li><li>How to cut between cameras depending on where the action in the scene is?</li><li>How to identify scenes within the game such as goals, penalties, or stoppages in play?</li><li>Which editing software should I use? How to use iMovie, DaVinci, Avid, Adobe, or something else?</li><li>How to pan / zoom cameras remotely?</li><li>How to do privacy blurring and remove identifiable information of a minor or somebody that did not agree to audio or video?</li><li>Is it possible to automate the insertion of titles, transitions, and backgrounds?</li><li>How to identify events like passes or shots and the players within the frame?</li><li>How to use streaming or other broadcast media platforms like YouTube, Vimeo, Twitch, and Mixer to share with fans and family that can’t make it to the game live?</li><li>What are the career paths and resources for somebody that really does want to become a videographer?</li><li>How to insert slow motion replays for key moments?</li><li>Are there tricks to make animated GIFs or highlight videos with slices of the game such as following a specific player?</li><li>Can I just buy a solution or is it worth building this on my own?</li></ul><p>It’s a long season, so to find these answers, I’ll post updates on Twitter where you can find me as <a href="https://twitter.com/jaysondelancey">@jaysondelancey</a>. It’s an exploration with a mix of the technical and creative aspects while also bringing in some experts along the way to share tips &amp; tricks of those that do this professionally as a career.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2a4901ce45db" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Developer Relations vs. the Volcano]]></title>
            <link>https://j12y.medium.com/developer-relations-vs-the-volcano-1a15025760b9?source=rss-f3c028e6e549------2</link>
            <guid isPermaLink="false">https://medium.com/p/1a15025760b9</guid>
            <category><![CDATA[marketing-strategies]]></category>
            <category><![CDATA[devrel]]></category>
            <category><![CDATA[developer-relations]]></category>
            <dc:creator><![CDATA[Jayson DeLancey]]></dc:creator>
            <pubDate>Sat, 27 Jul 2019 19:14:52 GMT</pubDate>
            <atom:updated>2019-07-27T19:30:07.057Z</atom:updated>
            <content:encoded><![CDATA[<p>In a recent post I shared my perspective <a href="https://medium.com/@j12y/what-is-developer-relations-931c1099d975">on Developer Relations</a> including the various activities one might observe from a DevRel organization. A few years ago I participated in a developer marketing campaign that helps illustrate how these various activities come together in practice. First though, somebody had to jump into a volcano.</p><h3>A Showcase Project</h3><blockquote>DevRel builds interesting projects, prototypes, and demonstrations by using the company’s products and APIs to understand what an external developer’s experience is. (<a href="http://Build interesting projects, prototypes, and demonstrations by using the products and APIs first">link</a>)</blockquote><p>As a Developer Evangelist with General Electric, I was often on the lookout for what I referred to as a showcase or hero project. Writing a tutorial, how-to, or other short demonstration can be done in a few days and can quickly validate that a service or API does what it says it does. Those are important, but to get a deeper understanding of what a developer’s experience is can come from using the product to build and support something of a larger scope that more closely resembles a production application or purpose.</p><p>In 2017, I learned about a collaboration that was beginning as part of a marketing campaign. A team was being assembled to go on an expedition to Nicaragua and install industrial IoT sensors in a volcano. It was a purpose-based mission to investigate the potential for outcomes like early-warning systems, preventative maintenance, and just a better understanding of our world. I’m not going to rehash it all here so to learn more about the story, project, and people involved — enjoy the website for an engaging scientific exploration (<a href="https://ge.com/digitalvolcano">https://ge.com/digitalvolcano</a>) but come back, I have more to tell about DevRel below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Zbx0fiuCAhKMqwQD6HwCWg.png" /><figcaption><a href="https://ge.com/digitalvolcano">https://ge.com/digitalvolcano</a></figcaption></figure><h3>Inspiring Others</h3><p>It sounded like a fascinating project when I heard the pitch so immediately asked how I could help. Ultimately, GE was not looking for any commercial viability in profiting from volcanoes, so this was an ideal project for DevRel to contribute software engineering resources to help develop. The data and source-code would not require any intellectual property protection so could be freely shared and talked about in public.</p><p>My involvement grew over time from initially just providing technical support to taking on an analytics dashboard. As an evangelist I didn’t have an engineering team to leverage, but it was an interesting enough project that I was able to persuade and recruit a half-dozen engineers from across the organization that were excited enough about the concept to contribute their personal time and energy to building the dashboard as a side-project of their regular jobs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uluz5Y4x2KKVY9aj8HCCgg.png" /><figcaption><a href="https://ge.com/digitalvolcano">https://ge.com/digitalvolcano</a></figcaption></figure><h3>SDKs and Reference Apps</h3><blockquote>DevRel develops tools and SDKs that help enable developers to onboard and have success faster and with less pain. (<a href="http://Build interesting projects, prototypes, and demonstrations by using the products and APIs first">link</a>)</blockquote><p>Once the industrial sensors were deployed from the expedition we were able to get a stream of data coming from the sensors to analyze. We wanted to store, query, and analyze this data so we chose Python as our development language to build a dashboard. One of our first observations was that there were no resources to help a Python developer get started. Every developer would benefit from some tools so we added that to our list of deliverables:</p><ul><li>Develop an SDK that can be downloaded and used in the client language. While postman and curl examples that were published by engineering and documentation teams were fine, they are a least common denominator. E<em>very</em> developer needs to write some client code to build an application, so why not make it easier for everybody by providing it directly so that authentication, orchestration, and error-handling were handled.</li><li>Develop a Reference Application that can be downloaded and used to deploy an application quickly. Every developer is capable of standing up an app, but is that the best use of their time in evaluating a new product? If somebody can get a prototype up and running in an hour rather than a week — that gives a much better impression of the platform.</li></ul><p>We felt the pain ourselves, built the resources, and made them available on GitHub.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/820/1*hWZ7ivObL09EhrDfV0EvFQ.png" /><figcaption><a href="https://github.com/j12y">https://github.com/j12y</a></figcaption></figure><h3>Getting Started Guides</h3><blockquote>DevRel creates technical documentation such as formal getting started guides and tutorials as well as informal blog posts. (<a href="http://Build interesting projects, prototypes, and demonstrations by using the products and APIs first">link</a>)</blockquote><p>Well written code is great but not everybody can learn from reading code alone. Often, the why and context must be explained. In DevRel, we want to help all developers with a variety of skill levels, so it’s important to explain things for both somebody who’s a beginner and for advanced cookbook recipes for solving specific technical challenges. The SDK and reference app for the volcano project were delivered with complete documentation to help others learn.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AZoDYzpn3vKVnGihrEjLhQ.png" /></figure><h3>Getting the Word Out</h3><blockquote>DevRel attends, speaks, and sponsors developer events like meetups, conferences, and hackathons delivering content through a variety of modalities like presentations, webinars, live coding, recorded videos, podcasts, workshops, etc. (<a href="http://Build interesting projects, prototypes, and demonstrations by using the products and APIs first">link</a>)</blockquote><p>It is considered taboo to sell a product with Developer Relations. Ultimately, an organization exists to make a profit though so if the product is priced correctly and the value exceeds its cost then anybody whether developer or not would consider buying. Therefore, DevRel does exist to “sell” but achieves this result indirectly.</p><ul><li>DevRel focuses on a long-term relationships rather than short-term transactions</li><li>DevRel focuses on providing something of immediate value for free whether somebody is buying or not</li></ul><p>That value frequently comes from the transfer of knowledge and access. To accomplish this, content is developed and delivered to wherever an audience exists that might benefit. The volcano project resulted in a lot of learning that can be shared with no strings attached.</p><ul><li>what our services were good for</li><li>what our services were not good for</li><li>what we learned from using those services in combination with other related technologies</li><li>what we learned about those related technologies</li><li>the tools we created that might make it easier for others trying to use any of our services or related technologies</li></ul><p>We had a new SDK and Reference App that we thought would be useful to others. Some developers might stumble upon them if they looked, but it was time to get the word out more proactively. We believed others might be interested in engaging with us long-term and could benefit from what we learned.</p><p>What did that campaign look like?</p><p><strong><em>We released blog posts on multiple sites telling the story in different ways.</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/533/1*sacgNffYhxMg27Lfszh_2Q.png" /><figcaption><a href="https://medium.com/@j12y/volcano-app-the-story-behind-the-python-reference-app-and-sdk-a8f7dba61556">https://medium.com/@j12y/volcano-app-the-story-behind-the-python-reference-app-and-sdk-a8f7dba61556</a></figcaption></figure><p><strong><em>We engaged Media Relations and journalists covered the story in </em></strong><a href="https://www.cnet.com/news/volcano-digital-ge-website-zipline-expedition-masaya-lava/"><strong><em>CNET</em></strong></a><strong><em>, </em></strong><a href="https://www.livescience.com/60299-virtual-tour-of-active-volcano.html"><strong><em>Live Science</em></strong></a><strong><em>, </em></strong><a href="https://observer.com/2017/09/general-electric-manaya-volcano-big-data-predictive-analytics/"><strong><em>Observer</em></strong></a><strong><em>, etc..</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/378/1*c9Jxg9hsCmQWlnCNIkn-Tw.jpeg" /></figure><p><strong><em>We posted to aggregators like HackerNews, Reddit, and </em></strong><a href="https://www.producthunt.com/posts/the-digital-volcano-from-ge"><strong><em>Product Hunt</em></strong></a><strong><em>.</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/564/1*ja37o4AwbNWLOlmIks_IAA.png" /></figure><p><strong><em>We created videos, podcasts, and webinars so that others could listen at the time, place, and format they preferred.</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/604/1*IgwZqtXAF2JdWzZVg65Ffw.png" /><figcaption><a href="https://www.stitcher.com/podcast/cals-podcast/iot-goes-industrial/e/52145922">https://www.stitcher.com/podcast/cals-podcast/iot-goes-industrial/e/52145922</a></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/711/1*AQiep_B6gUWemBbuVRfJtg.png" /><figcaption><a href="https://www.techgig.com/webinar/Source-Code-for-an-Active-Volcano-Predix-Python-SDK-1192">https://www.techgig.com/webinar/Source-Code-for-an-Active-Volcano-Predix-Python-SDK-1192</a></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/595/1*EBUSKsYrKYMrvDLlxvtbng.png" /><figcaption><a href="https://youtu.be/RBRqsjCnwCs">https://youtu.be/RBRqsjCnwCs</a></figcaption></figure><p><strong><em>We wanted to answer questions both live at events and through online support forums.</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fIDaqMU1dPMd7SNXb_1lpw.jpeg" /></figure><p>DevRel should avoid the bad rep that comes from a “sales pitch” by providing value through knowledge. To accomplish that requires a lot of engagement both online and in-person. It’s a job where functions like engineering, product, marketing, etc. should participate but as the commitment becomes a full-time job that’s why Developer Relations exists as an organization.</p><h3>Summary</h3><p>What does DevRel do? Installing sensors in a volcano is not your typical project. Most projects don’t need to be at this scope or scale to be effective (was this the most expensive SDK launch ever?) but it does illustrate a few best practices for doing developer relations:</p><ul><li>build <em>something</em> with your product, the experience first-hand is a good learning opportunity</li><li>provide tools like SDKs, reference apps, etc. that would have helped you because they’ll also help others</li><li>document the journey, the mistakes and learning you had along the way can help others save time</li><li>spread the word in as many places and ways as possible</li></ul><p>This was a project that got a high level of return for the engineering investment that went into it. Without DevRel this project would not have happened or had as much of an impact in helping other developers.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1a15025760b9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What is Developer Relations?]]></title>
            <link>https://j12y.medium.com/what-is-developer-relations-931c1099d975?source=rss-f3c028e6e549------2</link>
            <guid isPermaLink="false">https://medium.com/p/931c1099d975</guid>
            <category><![CDATA[evangelism]]></category>
            <category><![CDATA[developer-relations]]></category>
            <category><![CDATA[advocacy]]></category>
            <category><![CDATA[devrel]]></category>
            <dc:creator><![CDATA[Jayson DeLancey]]></dc:creator>
            <pubDate>Fri, 19 Jul 2019 15:49:45 GMT</pubDate>
            <atom:updated>2019-08-08T03:38:24.344Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Dt_qLC4Nw9LszSCB76uozg.png" /></figure><h3>What is DevRel?</h3><p>Here’s my take.</p><p><strong>Developer Relations</strong> (or DevRel) is the part of an organization that focuses on making sure a product is ready for adoption when the intended user is a software developer. A technical product is different because the audience for consuming it:</p><ul><li>doesn’t typically respond to traditional marketing tactics</li><li>doesn’t typically respond to traditional sales</li><li>is well informed and often capable of solving the problem themselves</li></ul><p>A product that is an API available on the cloud is a prime example, developers can either recommend or block the buying decision. Therefore, DevRel exists as a cross-functional team that aspires to <em>earn</em> that developer’s recommendation.</p><p>This can be done by ensuring a great <strong><em>developer experience</em></strong>, <strong><em>evangelizing</em></strong> the product to increase <strong>awareness</strong>, building a <strong><em>community</em></strong> within larger software ecosystems, <strong><em>advocating</em></strong> for changes in the product that help developers with <strong>adoption</strong>, and providing the <strong><em>support</em></strong> needed for developers to be successful building their own project by using yours.</p><p>Many large technology companies have DevRel teams and programs including AWS, Dolby, Google, Intel, IBM, Microsoft, Salesforce, Samsung, Twilio, etc.</p><figure><img alt="Quote from “The New Kingmakers” by Stephen O’Grady" src="https://cdn-images-1.medium.com/max/200/1*x73R3TovkogfEEhwNWfrDQ.png" /><figcaption>“Technology is increasingly being driven by bottom-up, rather than top-down, adoption… The days of recruiting developers to where you are is over. You have to go to where they are.” — Stephen O’Grady, The New Kingmakers</figcaption></figure><h3>What Does DevRel Do?</h3><p>There are a number of activities that can be grouped into the domain of Developer Relations. Depending on the stage of a product in its journey from development to general availability in the market will drive where DevRel’s priorities are.</p><ul><li>Attend, speak, and sponsor developer events such as meetups, conferences, and hackathons</li><li>Build interesting projects, prototypes, and demonstrations by using the products and APIs first</li><li>Create technical documentation both formal getting started guides or tutorials as well as informal blog posts</li><li>Deliver content through a variety of modalities — webinars, live coding sessions, recorded videos, podcast interviews, in-person workshops or presentations, etc.</li><li>Work with partnerships &amp; alliances for joint go to market collaboration opportunities with complementary services needed in building something</li><li>Grow communities online &amp; offline through newsletters, VIP programs, etc.</li><li>Provide technical support across channels that are convenient for developers including in-person events, online forums, stack overflow, quora, social media, etc.</li><li>Develop tools and SDKs that help enable developers to onboard and have success faster and with less pain</li></ul><blockquote><a href="https://medium.com/@j12y/developer-relations-vs-the-volcano-1a15025760b9">Digital Volcano Case Study</a> — look at my other story on a developer campaign that demonstrated some of these activities in action.</blockquote><p>To accomplish these activities DevRel must work in close collaboration with participation and interlock from many other departments across the organization such as Product Management, Engineering, Marketing, Communications, Public Relations, Legal, and Customer Support. This is part of what makes placing DevRel within an organization a common challenge. The whole organization must contribute to the mission, DevRel just focuses on it full-time across functions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/324/1*PlOGc6ial4lVU9RY_tVzOg.png" /><figcaption>Hoopy’s State of Developer Relations 2019 (<a href="https://devrel.net/dev-rel/state-of-developer-relations-2019">link</a>)</figcaption></figure><h3>What Skills Does Somebody in DevRel Have?</h3><p>The #1 most important skill for Developer Relations to have in their skillstack is <strong><em>empathy</em></strong>.</p><p>I was once told that at Google, the Developer Advocate is viewed as customer zero — an early stop in the release process to feel what the end developer will experience when trying to use an API in a project. This is not the same objective as Quality Assurance (QA) but more like user acceptance testing to get “Hello World” running efficiently within a developer’s preferred toolset. This means making sure the service is easy to learn, can be used in different environments, and can be used in combination with other products offered by the same company.</p><p>A DevRel organization requires a cross section of skills like:</p><ul><li>Software Development —a background in solutions architecture, polygot full-stack development use of web APIs, etc.</li><li>Communications — such as technical writing and public speaking, cross-functional interpersonal relationships</li><li>User Experience (UX) — such as User Centered Design, building developer productivity tools, etc.</li><li>Business — such as business development, partnerships &amp; alliances, public relations, etc.</li></ul><p>Depending on any individual’s specific strengths might prepare them for one of a number of typical developer relations roles (this is not the structure of a team, just examples of titles you might see):</p><ul><li>Developer Evangelist / Technical Evangelist — definitions vary, but frequently associated with representing the company to the community in order to sell the dream of what a product can do</li><li>Developer Advocate — often puts greater emphasis on representing the community to the company, expressing the feedback gathered from developers in the community to help shape the product direction while giving support</li><li>Community Manager / Events Manager — networker and facilitator for looking after the community, sharing information, making connections, or planning events</li><li>Developer Experience / Developer Programs Engineer — often works within the company by focusing on usability and engineering of developer tooling, hygiene around the APIs, building SDKs, tutorials and portals</li><li>Content Manager / Technical Writer — skilled at communicating clearly and effectively to audiences</li><li>Developer Marketing / Growth Hacking — succinctly crafting the message around what a product does so that it resonates with the developer audience trying to find it by cultivating social media, advertisements, and related tactics.</li></ul><h3>Summary</h3><p>I have been practicing Developer Relations for a number of years with direct visibility across multiple organizations so felt I could finally synthesize my perspective on what DevRel is for its impact on a business and industry. Many other sources influenced my point of view, so I’d call your attention to these other resources for additional perspectives:</p><ul><li>Christian Heilmann’s <a href="http://developer-evangelism.com/">Developer Evangelist Handbook</a></li><li>Matthew Revell’s DevRelCon and <a href="https://devrel.net/">devrel.net</a></li><li>Phil Leggetter’s <a href="https://www.leggetter.co.uk/2016/02/03/defining-developer-relations.html">Defining Developer Relations</a></li><li>Brandon West’s <a href="https://sendgrid.com/blog/3-cs-developer-relations/">The 3 C’s of Developer Relations</a></li><li>Mary Thengvall’s <a href="https://www.amazon.com/Business-Value-Developer-Relations-Communities/dp/1484237471/ref=as_li_ss_tl?ie=UTF8&amp;linkCode=sl1&amp;tag=persea-20&amp;linkId=e4a6e9164220ac63f4f807643935dd27">The Business Value of Developer Relations</a> and <a href="https://www.marythengvall.com/blog/2019/5/22/what-is-developer-relations-and-why-should-you-care">What Is Developer Relations (And Why Should You Care?)</a></li><li>Ashley McNamara’s <a href="https://medium.com/@ashleymcnamara/what-is-developer-advocacy-3a92442b627c">What is Developer Advocacy?</a></li><li>Robert Nyman’s <a href="https://dzone.com/articles/what-is-developer-relations-and-how-to-do-it">What Developer Relations Is and How to Do It</a></li><li>Reto Meier’s <a href="https://medium.com/google-developers/the-core-competencies-of-developer-relations-f3e1c04c0f5b">The Core Competencies of Developer Relations</a></li><li>…and many more</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=931c1099d975" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What I’ve Been Working On in 2018]]></title>
            <link>https://j12y.medium.com/what-ive-been-working-on-in-2018-b7904da1fba0?source=rss-f3c028e6e549------2</link>
            <guid isPermaLink="false">https://medium.com/p/b7904da1fba0</guid>
            <category><![CDATA[general-electric]]></category>
            <category><![CDATA[developer-relations]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[here-maps]]></category>
            <category><![CDATA[python]]></category>
            <dc:creator><![CDATA[Jayson DeLancey]]></dc:creator>
            <pubDate>Wed, 26 Dec 2018 22:27:12 GMT</pubDate>
            <atom:updated>2018-12-26T22:28:52.895Z</atom:updated>
            <content:encoded><![CDATA[<p>Last year, I did a round-up of <a href="https://medium.com/@j12y/what-would-you-say-you-do-here-a-look-back-at-2017-4eeb29b3b839">some of the things I worked on in 2017</a>. While 2018 didn’t include as many volcanoes, virus labs, or boats as the year prior — I worked on a few interesting projects while working for General Electric (GE) and part way through the year made the switch to join <a href="https://developer.here.com">HERE Technologies</a> in the Developer Relations group.</p><h3>Community — Makers</h3><p>I align myself closely with the maker community and had the fun task of building out a makerspace at GE Digital in San Ramon. With a small budget and the help of Rik Dryfoos we furnished the makerspace with 3D Printers, tools, electronic components, and a number of demos to help explain Industrial IoT concepts to corporate guests who visited the <a href="https://www.ge.com/digital/ge-digital-industrial-foundries">GE Digital Foundry</a>. We also developed some workshops and small group training while collaborating with other maker communities within GE at other offices such as Detroit, New Orleans, and then Crotonville.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/848/1*fxYcoNwN0GlfZQ-lxqGLGA.jpeg" /><figcaption>Solution Architects building a demo (top-left), Jeffrey Knapp leading a 3D printing class (top-right), and Rik Dryfoos running a Digital Industrial Workshop (bottom).</figcaption></figure><h3>Community — Open Source</h3><p>Another community that demonstrates the spirit of a rising tide lifts all boats is the open-source organizations within a company. Upon joining HERE Technologies, I was delighted to find the engineering teams actively engaged and doing some amazing work. I took a bit of a deep dive into a few of the projects that have been generously shared with the world in order to shine the spotlight on the engineers making it happen.</p><p><a href="https://developer.here.com/blog/visualizing-large-scale-terrain-with-open-source-tool-tin-terrain">Visualizing Large Scale 3D Terrain with Open Source Tools - HERE Developer</a></p><h3>J12Y on Twitter</h3><p>Learn from Victor Lu&#39;s blog post on the open-sourced Python package from @heredev called the Point Processing Tool Kit (PPTK) for visualizing millions of 3D point clouds such as GPS trajectories &amp;amp; LIDAR point clouds. A nice gift before the holidays. https://t.co/KnQx57f1Tl</p><h3>Events</h3><p>In the second half of 2018 I found myself on the road quite a bit. Including internal meetings, hackathons, and conferences where I visited Seattle, Los Angeles, Chicago, New York, Detroit, Kansas City, Austin, and Berlin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GDh0g2udworY_8OMT9uYyw.png" /><figcaption><a href="https://flightmapper.io/maps/jdelancey">https://flightmapper.io/maps/jdelancey</a></figcaption></figure><h4>Events — Speaking</h4><p>To share things I’ve learned along the way that might save somebody some time I had a few speaking sessions:</p><ul><li>Silicon Valley Code Camp — <a href="https://www.siliconvalley-codecamp.com/Session/2018/the-location-of-things-from-a-to-xyz">The Location of Things from A to XYZ</a></li><li>Developer Week — <a href="https://developerweekaustin2018.sched.com/event/HSBY/open-talk-making-maps-with-xyz">Making Maps with XYZ</a></li><li>AWS re:Invent — <a href="https://twitter.com/jaysondelancey/status/1068218647988957185">The Importance of Location for IoT</a></li><li>Webinar —<a href="https://go.engage.here.com/webinar-An-Intro-to-HERE-XYZ.html?cid=XYZ-Twitter-CM-0-Engage-0&amp;utm_source=Twitter&amp;utm_medium=social&amp;utm_campaign=CommsShare_2018Q4"> Mapping Seismic Activity, an Intro to HERE XYZ</a></li></ul><p>The first webinar is just the start and we are ready to announce many more coming in January.</p><h4>Events — Engaging</h4><p>Events are a great place to share information through speaking but even more than that it is a great way to learn about what others are building and ask questions. There were a handful of events where HERE Technologies sponsored hackathons or booths to meet with folks in the communities.</p><ul><li>Hack Midwest</li><li>TechCrunch</li><li>CalHacks</li><li>DroidCon NYC</li><li>State of the Maps US</li></ul><h3>J12Y on Twitter</h3><p>Congrats to team &quot;Collector&quot; for creating a fun geocaching application using @reactjs and @heredev at @CalHacks this weekend. Great to meet the team behind it too. #CalHacks5 #TeamPreston</p><p>Another great aspect of going to events is it is also a good chance to catch up with former colleagues when everybody has moved on to new roles and companies.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UG77I3bAkw0NwEMxj6mjjw.jpeg" /><figcaption>Impromptu AWS re:Invent reunion with Rackspace (left) and DreamWorks Animation (right)</figcaption></figure><h3>Content</h3><p>A key responsibility of my role is to advocate on behalf of the community internally to product teams. One way I do this is by building projects myself to stumble over any pain points before others do and channel that back as feedback to engineering or teach others some of the things I learned along the way in written tutorials.</p><h4>Content — React</h4><p>I haven’t been a front-end web developer for several years but I wanted to get back up to speed with one of the more popular frameworks — React. There had been a number of questions from the developer community about how to be successful with web components and location so I spent some time writing blog posts to describe some of the projects I built after learning more about how to use the library better myself.</p><ul><li><a href="https://developer.here.com/blog/here-matrix-routing-with-reactjs-to-optimize-your-black-friday">HERE Matrix Routing with ReactJS to Optimize Your Black Friday</a></li><li><a href="https://developer.here.com/blog/use-here-interactive-maps-with-reactjs-to-pick-a-theme">Use HERE Interactive Maps with ReactJS to Pick a Theme</a></li><li><a href="https://developer.here.com/blog/street-address-validation-with-reactjs-and-here-geocoder-autocomplete">Street Address Form Validation with ReactJS and HERE Geocoder Autocomplete</a></li><li><a href="https://developer.here.com/blog/here-with-react-location-based-todo-app">A Location Based TODO App</a></li></ul><h3>J12Y on Twitter</h3><p>How to Use HERE Interactive Maps with React JS, a tutorial and demo of building a map theme / style picker @heredev #ReactJS #JavaScript https://t.co/hvTscWifx3</p><p>I have a few more projects in progress with ReactJS so expect a few more over the next few months.</p><h4>Content-Google Alternatives</h4><p>Another theme I focused on was to provide some guidance for developers and engineering teams feeling the impact of <a href="https://geoawesomeness.com/google-introduces-new-pricing-plans-for-maps-api/">Google’s decision to raise prices</a>. Google has been successful with their consumer application that many developers didn’t even realize there were alternatives such as HERE Technologies, myself included. Once you get a chance to explore the HERE services you often can build the same applications. I wrote a few posts to help highlight a few difference to try and make those migrations easier:</p><ul><li><a href="https://developer.here.com/blog/how-to-migrate-kml-from-google-to-here-maps-and-xyz">How-to Migrate KML to HERE Maps</a></li><li><a href="https://developer.here.com/blog/how-to-migrate-from-google-routes-to-here-routing">How-to Migrate from Google Routes to HERE Routing</a></li><li><a href="https://developer.here.com/blog/how-to-migrate-from-google-places-to-here-geocoder-search">How-to Migrate from Google Places to HERE Geocoder</a></li><li><a href="https://developer.here.com/blog/how-to-create-a-here-dynamic-map-like-google-maps">How-to Migrate from Google Maps to HERE Maps</a></li></ul><p>We also put together a <a href="https://engage.here.com/switch">freemium SwitchToHERE</a> site that helps learn the basics like these and covers a few more done with the help of some of my teammates.</p><h4>Content-Developer Blog</h4><p>I’ve spent a great deal of time to help shape the voice and technical depth of the <a href="https://developer.here.com/blog">HERE Developer Blog</a> by authoring posts myself, working with teammates, and mentoring other writers to help them tell their story. Here’s a sample:</p><ul><li><a href="https://developer.here.com/blog/managing-and-visualizing-geospatial-data-here-xyz-now-in-beta">Making Maps with HERE XYZ</a></li><li><a href="https://developer.here.com/blog/building-an-app-routing-to-water-fountains-here-xyz">Building an App for Routing to Nearby Water Fountains</a> by Boris Guenebaut</li><li><a href="https://developer.here.com/blog/turn-text-into-here-maps-with-python-nltk">Turn Text Into Maps with Python NLTK</a></li><li><a href="https://developer.here.com/blog/turn-text-into-here-maps-with-python-nltk">Safely Route College Students Using the HERE iOS SDK</a> by Brandon David</li><li><a href="https://developer.here.com/blog/run-circles-around-geojson-beginner-to-advanced-with-here-xyz">Run Circles Around GeoJSON, Beginner to Advanced</a></li></ul><p><a href="https://medium.com/@j12y/know-your-location-voiding-my-firefox-warranty-7566bdb4a36">Know Your Location — Voiding My Firefox Warranty</a></p><h3>What’s Next</h3><p>I’ve been gathering and preparing a lot more events and content for 2019 so if you like Python, Open-Source, Robotics, Autonomous Driving, and Cloud Services stay tuned for more next year.</p><p>Thanks, Happy Holidays and Happy New Year.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b7904da1fba0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Developer Relations: What makes a Good Webinar Strategy?]]></title>
            <link>https://j12y.medium.com/developer-relations-what-makes-a-good-webinar-strategy-6ac36e3eb53a?source=rss-f3c028e6e549------2</link>
            <guid isPermaLink="false">https://medium.com/p/6ac36e3eb53a</guid>
            <category><![CDATA[webinar-tips]]></category>
            <dc:creator><![CDATA[Jayson DeLancey]]></dc:creator>
            <pubDate>Fri, 21 Dec 2018 06:37:06 GMT</pubDate>
            <atom:updated>2018-12-23T02:12:17.513Z</atom:updated>
            <content:encoded><![CDATA[<p>I’ve presented in a <a href="https://go.engage.here.com/webinar-An-Intro-to-HERE-XYZ.html">few webinars for developers</a> in the past but not enough to have good data on what constitutes an optimal webinar strategy. I’m posting in hopes others might take pity and share their evidence / references to help me make an informed decision.</p><p>Key Topics:</p><ul><li>Webinar Frequency — how often should you do a webinar, how often should you repeat content previously presented in a webinar.</li><li>Live vs. Pre-recorded</li><li>Software</li><li>Scheduling</li></ul><h3>WEBINAR FREQUENCY</h3><p>I’m comparing two options for a webinar frequency decision:</p><blockquote>One and Done Strategy — Run webinar on a topic once and then make the recording available to anybody that registers after the originally scheduled event.</blockquote><blockquote>Amortization Strategy — Run webinar on a topic multiple times and still make the recording available, but repeat the live session again periodically (each quarter) to offer opportunity for Q&amp;A and minor changes / updates.</blockquote><p><strong><em>EFFORT</em></strong></p><p>There is effort involved in producing new content and promoting it in a webinar. A few rough estimates of the amount of time involved with each activity:</p><ul><li>Create new content (2–3 weeks)</li><li>Marketing for an upcoming webinar (1–2 days)</li><li>Deliver content at the scheduled time (1–2 hours)</li></ul><p>There is inevitably some follow-up questions from participants as well that take time which is expected. There doesn’t seem to be an added cost of hosting more than one webinar (fixed monthly cost) and I’m assuming no advertising expenses relying only on organic leads.</p><p><strong><em>RETURN</em></strong></p><p>If the content being delivered has value to the audience then we should see registrations. I’d hazard a few assumptions:</p><ul><li>Some cannot attend due to a scheduling conflict no matter when you schedule it</li><li>Some cannot attend because they were unaware it was happening until after the fact</li><li>Human behavior is to commit to spending time in a scheduled webinar but less likely to watching a recording of one on-demand that can be viewed anytime</li><li>Some will find significant value in the opportunity to participate and ask the host questions which doesn’t happen with recorded session</li><li>Incremental cost of repeating a session is smaller than the effort of creating it the first time or creating new content for a separate webinar</li><li>One can more successfully promote future upcoming webinars than recordings of past webinars — through newsletters, social media, web sites, etc. even if we’ve done the topic of that webinar in the past</li><li>If the webinar was valuable, those who attended the first time will send news of a second occurrence to colleagues</li></ul><p><strong><em>SUMMARY</em></strong></p><p>My hypothesis is that the <em>Amortization Strategy</em> is the better approach where better is measured by the number of registered participants who get value from the webinar. I’d welcome any evidence based perspectives that might change my mind and save me from a long period of learning from mistakes.</p><p>Using some fuzzy napkin math to estimate a model of attendance over the course of 12 months.</p><ul><li>Attendance (as with meetups) would be 1/3 of registrations though some that missed will probably watch the recording later</li><li>For <em>n</em> attendees, there is a factor for each subsequent event of new registrations. I’d expect the second instance to be better attended than the first if announced at the same time for instance. I’m using 1.0, 1.25, 0.75, and 0.5 as factors against <em>n</em> if running same content each quarter.</li></ul><p>With that model in mind, the <em>Amortization Strategy</em> would yield a 352% increase in registrations per original content produced and 163% more over the course of the year even accounting for the opportunity cost of fewer new original presentations.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6ac36e3eb53a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Turn Text Into HERE Maps with Python NLTK]]></title>
            <link>https://j12y.medium.com/turn-text-into-here-maps-with-python-nltk-here-developer-2f9d757b06bb?source=rss-f3c028e6e549------2</link>
            <guid isPermaLink="false">https://medium.com/p/2f9d757b06bb</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[nltk]]></category>
            <category><![CDATA[here-maps]]></category>
            <dc:creator><![CDATA[Jayson DeLancey]]></dc:creator>
            <pubDate>Sat, 27 Oct 2018 17:36:30 GMT</pubDate>
            <atom:updated>2018-10-27T18:02:27.221Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/509/1*nS8Oa-unzyjhU0_97kyVxw.png" /></figure><p><em>Originally published at </em><a href="https://developer.here.com/blog/turn-text-into-here-maps-with-python-nltk"><em>developer.here.com</em></a><em> so check out the original too.</em></p><p>What is in your Top 5 travel destinations? I asked my 8 year old son this recently and the response surprised me. The answer was very specific and unfamiliar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/387/1*IYkXIqjHUzbRZWCzvxlH_A.jpeg" /></figure><p>OK, I know Venice but I’m a software engineer in Northern California and haven’t studied geography in quite some time. I have to admit I have no idea where some of those places are.</p><p>Maybe you have found yourself reading a travel article that beautifully describes a glamorous locale, places to stay, visit, and where to eat. These articles can be swell, but a simple map can go a long way to add the context of place that some expertly crafted prose alone cannot do. If the author or publisher didn’t include a map for you and you don’t have an 8-yr old Geography savant in your house, Python can help.</p><h3>Solution</h3><p>To solve this problem we will stand up a Python Flask server that exposes a few APIs to</p><ol><li>Download a given URL and parse the HTML with BeautifulSoup.</li><li>Extract locations from the text based on some clues with the Natural Language Toolkit (NLTK).</li><li>Geocode the location to determine a latitude and longitude with the <a href="https://developer.here.com/documentation#geocoder">HERE Geocoder API</a>.</li><li>Place markers on a map to identify the recognized places with the <a href="https://developer.here.com/documentation/map-image/topics/quick-start-show-default-location.html">HERE Map Image API</a>.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/884/0*yjmsDpgomiveS7fJ.png" /></figure><h3>Server Setup</h3><p>For this section I make an assumption you are running an environment like OSX or Linux. If you are running Windows you will need to adjust some of the commands a bit.</p><h3>Configuration</h3><p>With <a href="https://12factor.net/">the Twelve-Factor App</a> the case is made that a best practice is to <a href="https://12factor.net/config">store config in the environment</a>. I agree and like to store my API credentials in variables APP_ID_HERE and APP_CODE_HERE found in a file called <strong>HERE.sh</strong>.</p><pre>#!/bin/bash <br>export APP_ID_HERE=your-app-id-here <br>export APP_CODE_HERE=your-app-code-here</pre><p>I source it into my environment with . HERE.sh to avoid any hard-coded credentials accidentally being released with my source.</p><h3>Structure</h3><p>The web server component will need several files you can see summarized in the listing below. Start by running mkdir -p app/api_1_0.</p><pre>├── app   <br>|   ├── __init__.py <br>│   └── api_1_0 <br>│       ├── __init__.py <br>│       ├── demo.py <br>│       ├── health.py <br>├── HERE.sh <br>├── manage.py <br>├── config.py <br>└── requirements.txt</pre><p>If you aren’t using Virtual Environments for Python you should be. You can find more from the <a href="https://docs.python-guide.org/starting/installation/">Hitchiker’s Guide to Python</a> to get off on the right footing. You’ll want to initialize your environment with the libraries in requirements.txt which can be done with pip install -r requirements.txt if the <strong>requirements.txt</strong> contains the following dependencies.</p><pre>Flask<br>Flask-Script<br>gunicorn<br>nltk<br>requests</pre><h3>App</h3><p>We will use <strong>manage.py</strong> as the main entrypoint to our application. It looks like the following listing:</p><pre>import os<br>import app from flask_script<br>import Manager, Server<br>app = app.create_app(&#39;default&#39;)<br>manager = Manager(app)</pre><pre>if __name__ == &#39;__main__&#39;:<br>  port = os.environ(&#39;PORT&#39;, 8000)<br>  manager.add_command(&#39;runserver&#39;, Server(port=port))<br>  manager.run()</pre><p>I’ve left out a few niceties like logging and printing the URL for brevity. This isn’t particularly interesting to our task and is just some housekeeping to run a simple server for our APIs.</p><p>The <strong>config.py</strong> is also important for pulling in some of those environment variables we’ll need to reference later.</p><pre>import os</pre><pre>class Config(object):<br>    SECRET_KEY = os.environ.get(&#39;FLASK_SECRET_KEY&#39;)<br>    APP_ID_HERE = os.environ.get(&#39;APP_ID_HERE&#39;)<br>    APP_CODE_HERE = os.environ.get(&#39;APP_CODE_HERE&#39;)</pre><pre>    @staticmethod<br>    def init_app(app):<br>        pass </pre><pre>config = {&#39;default&#39;: Config}</pre><p>Unlike other Python projects, our init files are pretty important on this one. In <strong>app/init.py</strong> we define the create_app function we saw in <strong>manage.py</strong>.</p><pre>from config import config<br>from flask import Flask</pre><pre>def create_app(config_name):<br>    app = Flask(__name__)   <br>    app.config.from_object(config[config_name]) <br>    config[config_name].init_app(app)</pre><pre>    from .api_1_0 import api as api_1_0_blueprint <br>    app.register_blueprint(api_1_0_blueprint, url_prefix=&#39;/api/1.0&#39;) </pre><pre>    return app</pre><p>This gives us nice clean api versioning for any resources in our API. We also need to define <strong>app/api_1_0/init.py</strong> with some configuration</p><pre>from flask import Blueprint<br>api = Blueprint(&#39;api&#39;, __name__)</pre><pre>from . import health<br>from . import demo</pre><p>As you can see, we do need to make sure each library we create is identified as part of the blueprint.</p><h3>Healthcheck</h3><p>To make sure our server is running properly we can add a quick healthcheck endpoint in the file <strong>app/api_1_0/healthcheck.py</strong>.</p><pre>from flask import jsonify<br>from flask import current_app as app<br>from . import api</pre><pre>@api.route(&#39;/health&#39;, methods=[&#39;GET&#39;])<br>def handle_health():<br>    return jsonify({<br>        &#39;hello&#39;: &#39;world&#39;,<br>        &#39;app_id_here&#39;: app.config[&#39;APP_ID_HERE&#39;],<br>        &#39;app_code_here&#39;: app.config[&#39;APP_CODE_HERE&#39;]<br>        })</pre><p>At this point we should be able to run python manage.py runserver and have proof of life. If you use your browser to go to http://localhost:8000/healthcheck we should get a response that confirms our server is up and has our app_id and app_code properly configured.</p><p>You may not want to display this once you hit production but is fine while we’re at a “hello world” stage.</p><h3>Text</h3><p>For the purposes of getting started I will use a simple text file with just the locations from before.</p><pre>Venice<br>Mdina<br>Aswan<br>Soro<br>Gryfino</pre><p>For more complex data sets to test with I recommend just trying out something from the <a href="https://www.nytimes.com/section/travel">New York Times</a>, <a href="https://www.wsj.com/news/life-arts/travel">Wall Street Journal</a>, or <a href="http://www.bbc.com/travel">BBC</a> travel sections.</p><h3>Extract</h3><p>We need to extract text from HTML and tokenize any words found that might be a location. We will define a method to handle requests for the resource <strong>/tokens</strong> so that we can look at each step independently.</p><pre>@api.route(&#39;/tokens&#39;, methods=[&#39;GET&#39;])<br>def handle_tokenize():<br>  # Take URL as input and fetch the body<br>  url = request.args.get(&#39;url&#39;)<br>  response = session.get(&#39;url&#39;)<br><br>  # Parse HTML from the given URL<br>  body = BeautifulSoup(response.content, &#39;html.parser&#39;)<br><br>  # Remove JavaScript and CSS from our life<br>  for script in body([&#39;script&#39;, &#39;style&#39;]):<br>    script.decompose()<br><br>  text = body.get_text()<br><br>  # Ignore punctuation<br>  tokenizer = RegexpTokenizer(r&#39;\w+&#39;)<br><br>  # Ignore duplicates<br>  tokens = set(tokenizer.tokenize(text))<br><br>  # Remove any stop words<br>  stop_words_set = set(stopwords.words())<br>  tokens = [w for w in tokens if not w in stop_words_set]<br><br>  # Now just get proper nouns<br>  tagged = pos_tag(tokens)<br>  tokens = [w for w,pos in tagged if pos in [&#39;NNP&#39;, &#39;NNPS&#39;]]<br><br>  return jsonify(list(tokens))</pre><p>Before this will work, we need to download NLTK resources. This is a one-time operation you can do in an interactive python shell or by executing a simple script.</p><pre>$ python<br>...<br>&gt;&gt;&gt; import nltk<br>&gt;&gt;&gt; nltk.download(&#39;stopwords&#39;)<br>&gt;&gt;&gt; nltk.download(&#39;averaged_perceptron_tagger&#39;)</pre><p>With this <strong>demo.py</strong> in place we can restart our server and call the following endpoint to get back a list of any terms that could potentially be locations.</p><pre>#!/bin/bash<br>curl <a href="http://localhost:8000/api/1.0/tokens?url=$1">http://localhost:8000/api/1.0/tokens?url=$1</a></pre><p>For example, if you were looking at “<a href="https://www.nytimes.com/2018/10/15/travel/biking-the-open-road-in-colorado-with-a-few-bumps-along-the-way.html?rref=collection%2Fsectioncollection%2Ftravel&amp;action=click&amp;contentCollection=travel&amp;region=rank&amp;module=package&amp;version=highlights&amp;contentPlacement=1&amp;pgtype=sectionfront">Biking the Open Road in Colorado, With a Few Bumps Along the Way</a>” this returns a response including terms like:</p><pre>[&quot;Retreat&quot;,&quot;Industry&quot;,&quot;Boushnak&quot;,&quot;Frise&quot;,&quot;National&quot;,&quot;Mesa&quot;,&quot;Chicago&quot;,&quot;Washington&quot;,&quot;Forest&quot;,&quot;Angeles&quot;,&quot;Canyons&quot;,&quot;Colorado&quot;,...]</pre><p>We’ve trimmed the wordcount down dramatically from the original article but there is still much more work that could be done to fine tune this recognition process. This is good enough for a first pass though without adding more complexity. There is obviously still some noise and not all of these are locations, but that’s what we can use the HERE Geocoder to help with.</p><h3>Geocode</h3><p>The HERE Geocoder API very simply takes a human understandable location and turns it into geocordinates. If you put in an address, you get back latitude and longitude.</p><p>Here’s the listing for a geocoder endpoint:</p><pre>@api.route(&#39;/geocode&#39;, methods=[&#39;GET&#39;])<br>def handle_geocode():<br>  uri = &#39;https://geocoder.api.here.com/6.2/geocode.json&#39;<br>  headers = {}<br>  params = {<br>    &#39;app_id&#39;: app.config[&#39;APP_ID_HERE&#39;],<br>    &#39;app_code&#39;: app.config[&#39;APP_CODE_HERE&#39;],<br>    &#39;searchtext&#39;: request.args.get(&#39;searchtext&#39;)<br>  }    <br><br>  response = session.get(uri, headers=headers, params=params)<br>  return jsonify(response.json())</pre><p>Restart the python webserver and send a request for a city like “Gryfino”:</p><pre>#!/bin/bash<br>curl http://localhost:8000/api/1.0/geocode?searchtext=$1</pre><p>The response includes among other things the location I might put a marker to display this position on a map.</p><pre>&quot;DisplayPosition&quot;: { &quot;Latitude&quot;: 53.25676, &quot;Longitude&quot;: 14.48947 } </pre><h3>Map</h3><p>Finally, we’re going to take the latitude and longitude we received from our geocode request and generate a simple render with the HERE Map Image API.</p><p>This listing looks like the following:</p><pre>@api.route(&#39;/mapview&#39;, methods=[&#39;GET&#39;])<br>def handle_mapview():<br>  uri = &#39;https://image.maps.api.here.com/mia/1.6/mapview&#39;<br>  headers = {}<br>  params = {<br>    &#39;app_id&#39;: app.config[&#39;APP_ID_HERE&#39;],<br>    &#39;app_code&#39;: app.config[&#39;APP_CODE_HERE&#39;],<br>    &#39;poi&#39;: request.args.get(&#39;poi&#39;)<br>  }<br><br>  response = session.get(uri, headers=headers, params=params)<br>  image_path = tempfile.mktemp()<br>  open(image_path, &#39;wb&#39;).write(response.content)<br><br>  return image_path</pre><p>For simplicity and brevity I haven’t included any of the error / response handling you should do here. I’ve also cheated a bit by just storing the image to the local filesystem for illustration.</p><p>Now by calling this endpoint with a comma-separated list of latitude, longitude pairs it will return a map with all of the locations having markers.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*jV6a9WDWJIAMcY4q.png" /></figure><p>Place names without additional context can be ambiguous so in some cases there was more than one match. This map is only showing the first match, despite how much fun Venice beach may be.</p><h3>Summary</h3><p>The reason for making /tokens, /geocode, and /mapview separate endpoints is that this illustrates how you might setup microservices with Python + Flask for each operation you want to perform. This would allow a deployment to scale them independently.</p><p>You can find the full source code listing in the <a href="https://github.com/j12y/text-to-map-python-flask-nltk-here">GitHub project</a>.</p><p>For an extra dose of inception, try running the code and processing this article itself if you are still curious where to find Aswan and Gryfino.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2f9d757b06bb" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Know Your Location — Voiding My Firefox Warranty]]></title>
            <link>https://j12y.medium.com/know-your-location-voiding-my-firefox-warranty-7566bdb4a36?source=rss-f3c028e6e549------2</link>
            <guid isPermaLink="false">https://medium.com/p/7566bdb4a36</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[positioning]]></category>
            <category><![CDATA[geolocation]]></category>
            <category><![CDATA[firefox]]></category>
            <dc:creator><![CDATA[Jayson DeLancey]]></dc:creator>
            <pubDate>Wed, 18 Jul 2018 23:40:03 GMT</pubDate>
            <atom:updated>2018-07-25T17:07:56.697Z</atom:updated>
            <content:encoded><![CDATA[<p>I have to admit ignorance that I’ve answered the `${site} wants to know your location` question many times without thinking very deeply about what it means, both in terms of privacy or how it works technically.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/356/1*TD7BoQcqitXaEmjHdFXXLg.png" /></figure><p>I’m guessing that sometime in the past 5 years you’ve seen it too, so what’s going on behind the scenes and how might you use this in developing applications?</p><h3>The Geolocation API</h3><p>In order to make an application user-friendly, it makes good sense to know where the location of the user is. Things like places can be made more relevant, navigation and routing can be started sooner, your “things” can be found more quickly, and you don’t have to walk up-and-down all the aisles in the store looking for your mom.</p><p>If you try to solve this problem of determining the position <strong>server-side</strong>, the best indicator is generally the public IP address often reported in the <a href="https://en.wikipedia.org/wiki/X-Forwarded-For">X-Forwarded-For</a> header of the HTTP request. When you are using a virtual private network (VPN) or a proxy server, that could make it look like you are 300 miles away from where you actually are. This location may be accurate enough for localization (l10n) and internationalization (i18n) use cases of country origin, but not much more than that.</p><p>You can solve it <strong>client-side</strong> too with the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API">Geolocation API</a> which is much more accurate. Published as a recommendation by the World Wide Web Consortium in 2013, the API allows us to write JavaScript code to fetch a position:</p><pre>navigator.geolocation.getCurrentPosition(function(position) {    <br>     console.log(position); <br>});</pre><p>You can try this in a web console yourself and get back latitude and longitude values along with an approximate accuracy expressed as the radius in meters.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QLNjqJ2MG4mvLmz9pbDgEg.png" /><figcaption>Web Console Output</figcaption></figure><p>This makes sense for a mobile device that has a built-in GPS, but last time I checked I didn’t have a dongle for a GPS on my MacBook Pro. That made me curious about how browsers are implementing the spec.</p><h3>Void Your Firefox Warranty</h3><p>Firefox has a number of configuration settings you can modify to customize your experience. By typing “<em>about:config</em>” instead of a URL you can identify the settings for geo.wifi.uri which points to a googleapis endpoint.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*a-5fwT0vXSFZ_WcdiRYmdA.png" /><figcaption>geolocate service</figcaption></figure><p>I wanted to see what these requests look like so started a local webserver with <a href="https://www.npmjs.com/package/http-echo-server">http-echo-server</a> and updated the Firefox value of <strong>geo.wifi.url</strong> to point it tohttp://localhost:8000 so I could watch the traffic.</p><pre>$ npm install http-echo-server<br>$ http-echo-server<br>[server] event: listening (port: 8000)<br>[server] event: connection (socket#1)<br>[socket#1] event: resume<br>[socket#1] event: data<br>--&gt; POST / HTTP/1.1<br>--&gt; Host: localhost:8000<br>--&gt; User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:60.0) Gecko/20100101 Firefox/60.0<br>--&gt; Accept: */*<br>--&gt; Accept-Language: en-US,en;q=0.5<br>--&gt; Accept-Encoding: gzip, deflate<br>--&gt; Content-Type: application/json; charset=UTF-8<br>--&gt; Content-Length: 1198<br>--&gt; Connection: keep-alive<br>--&gt;<br>--&gt; {&quot;wifiAccessPoints&quot;:[{&quot;macAddress&quot;:&quot;81:3a:a9:88:80:58&quot;,&quot;signalStrength&quot;:-85},{&quot;macAddress&quot;:&quot;4c:97:6d:79:42:bf&quot;,&quot;signalStrength&quot;:-88},{&quot;macAddress&quot;:&quot;74:bc:0c:7f:0b:19&quot;,&quot;signalStrength&quot;:-84},{&quot;macAddress&quot;:&quot;00:a7:42:be:72:7f&quot;,&quot;signalStrength&quot;:-71},{&quot;macAddress&quot;:&quot;4c:66:6d:79:40:df&quot;,&quot;signalStrength&quot;:-85},<br>...]}</pre><p>As you can see, Firefox is scanning the wireless local area network (WLAN) to identify the mac addresses nearby and received signal strength indication (RSSI) values and sending it all to a web service. If I make this request myself, I might get back a location like:</p><pre>{<br>  &quot;location&quot;: {<br>     &quot;lat&quot;: 20.6842849,<br>     &quot;lng&quot;: -88.567782<br>  },<br>  &quot;accuracy&quot;: 101.0<br>}</pre><p>This is the data that feeds back into the Geolocation API we used earlier. You can learn more about this in the <a href="https://support.mozilla.org/en-US/kb/does-firefox-share-my-location-websites?redirectlocale=en-US&amp;redirectslug=does-firefox-share-my-location-web-sites">Firefox docs</a>. Chrome does the same thing but doesn’t let you choose a different provider as far as I can tell.</p><h3>HERE Positioning API</h3><p>If I wanted to test my web app with a specific location, I could store this static response in a file called test-location.json and set the <strong>geo.wifi.uri</strong> to point to the file on disk instead of an http endpoint.</p><p>I’d like to see a more dynamic result though and started exploring the <a href="https://developer.here.com/documentation/positioning/topics/request-first-locate.html">HERE Positioning API</a>. The HERE Positioning API works in much the same way as the default, taking in <strong>WLAN</strong> data but it also supports other radio bands — GSM, LTE, WCDMA, Cell. The Positioning API responds with JSON that Firefox expects, but I’ll need to insert a man-in-the-middle to modify the body of the request. The following listing demonstrates how I accomplished that.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b5257daf77acb089c3de8a0979d29382/href">https://medium.com/media/b5257daf77acb089c3de8a0979d29382/href</a></iframe><p>I could continue to use the <a href="https://developer.here.com/documentation/positioning/topics/request-first-locate.html">HERE Positioning API</a> with Firefox, but this was more of a learning experiment than my recommendation to stand up your own service. I have other plans for how I’d like to use the Geolocation and Positioning APIs which I’ll go into detail another time.</p><p>Until then, if you have any thoughts, questions, or pointers for more information to share reach out and let me know.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1JAG6RRuoRPvITq9OLK8Rg.jpeg" /><figcaption>Fox hugging a map.</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7566bdb4a36" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Predix Python SDK 1.0 Release Roundup]]></title>
            <link>https://j12y.medium.com/predix-python-sdk-1-0-release-roundup-fac862672f51?source=rss-f3c028e6e549------2</link>
            <guid isPermaLink="false">https://medium.com/p/fac862672f51</guid>
            <category><![CDATA[predix]]></category>
            <category><![CDATA[cloud-foundry]]></category>
            <category><![CDATA[redis]]></category>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[python3]]></category>
            <dc:creator><![CDATA[Jayson DeLancey]]></dc:creator>
            <pubDate>Wed, 21 Mar 2018 06:11:00 GMT</pubDate>
            <atom:updated>2018-03-21T06:11:00.189Z</atom:updated>
            <content:encoded><![CDATA[<p>The <a href="https://medium.com/@j12y/volcano-app-the-story-behind-the-python-reference-app-and-sdk-a8f7dba61556">GE Digital Volcano App</a> came out last summer with an early version of the Predix Python SDK known as <a href="https://github.com/PredixDev/predixpy">PredixPy</a>. This is a client library that is ready to help Python developers get started with many Predix Services in 10 lines of code or less.</p><p>This newest release candidate includes:</p><ul><li>verified to work on Python 3.6 and Python 2.7</li><li>allows you to encrypt your manifest configuration files</li><li>provides more flexibility for object initialization</li><li>supports Predix Cache (Redis)</li><li>supports Predix Database as a Service (PostgreSQL)</li><li>supports Predix Event Hub</li><li>supports UAA user management CRUD operations</li><li>more unit and integration test coverage</li><li>bug fixes, performance improvements, more documentation</li></ul><p>That’s enough change that this can be called version 1.0. If you find the project to be useful, please check it out on GitHub at <a href="https://github.com/PredixDev/predixpy/stargazers">PredixDev/predixpy</a> and let us know what you like or want to see from the project.</p><h3>MCVE</h3><p>As a best practice for asking questions on Stack Overflow you frequently should provide a Minimal, Complete, and Verifiable Example to demonstrate a problem. For the rest of this post, I’d like to provide MVCEs for solutions that PredixPy can now provide.</p><p>You can find many more examples in the <a href="https://predixpy.run.aws-usw02-pr.ice.predix.io/cookbook/index.html">PredixPy Cookbook</a>.</p><h3>Manifest Encryption</h3><p>If you are pushing apps to Cloud Foundry, chances are you will have a manifest.yml file. PredixPy is flexible enough that you don’t have to store configuration details in the manifest, but it’s there so that is the default place the SDK looks for reading/writing details like uris, <strong>Predix-Zone-Id</strong> and client id/secrets.</p><p>This can make some developers uncomfortable that the manifest could be checked into a public source code repository with the credentials exposed. The Predix App Framework that is part of PredixPy now allows you to encrypt those values by adding a parameter when you initialize the Manifest.</p><pre>In [1]: import predix.admin.app<br>In [2]: admin = predix.admin.app.Manifest(encrypted=True)</pre><p>By default it will not encrypt them and you need to pass them to your app afterall anyway but you will see a warning about it.</p><pre>In [3]: admin.write_manifest(&#39;manifest.secrets.yml&#39;, encrypted=False)<br>WARNING:root:Writing manifest manifest.yml unencrypted.</pre><pre>In [4]: admin.write_manifest(&#39;manifest.yml&#39;, encrypted=True)</pre><p>I still wouldn’t check it into a public repository, but at least it can be encrypted while at rest.</p><p>In addition to encrypting the manifest, I get tired of coming up with client ids and secrets all the time. The docs often show the following example:</p><pre>admin.create_client(&#39;client-id&#39;, &#39;client-secret&#39;)</pre><p>These are now keyword arguments so you can continue to pass them in the original order yourself, or allow the SDK to generate a guid to use as the client id and a cryptographically-secure pseudorandom letter, digit, punctuation generator as a temporary secret that meets password guidelines.</p><pre>admin.create_client()</pre><p>That should clean up some of the samples that are tempting to copy and paste without changing example client ids and secrets.</p><h3>Service Object Initialization</h3><p>PredixPy tries to make greenfield projects easy by giving control of the whole service instance lifecycle from creation / provisioning to data ingestion and consumption. Some projects don’t need all that automation, so now there is a bit more flexibility in using any of the services from Python.</p><p>The parameters needed can be passed in as keyword arguments like the following example demonstrates:</p><pre>In [1]: import predix.security.acs</pre><pre>In [2]: acs = predix.security.acs.AccessControl?<br>Init signature: predix.security.acs.AccessControl(uri=None, zone_id=None, *args, **kwargs)</pre><p>You can explicitly pass whatever uri and zone_id you want to use. If you don’t pass any values, the default behavior is to:</p><ul><li>Check if VCAP variables are defined (as they would be in the Predix Cloud for bound services)</li><li>Check for PredixPy environment variables, which are defined in the manifest.yml if you used PredixPy to create the service initially</li></ul><p>This is all described in the <a href="https://predixpy.run.aws-usw02-pr.ice.predix.io/getting-started/index.html#concepts">Getting Started Concepts</a> but works more consistently across all the supported services now.</p><h3>Redis and PostgreSQL</h3><p>You can now create these data management services by scripting it in Python:</p><pre>import predix.admin.app<br>admin = predix.admin.app.Manifest()<br>admin.create_cache()<br>admin.create_dbaas()</pre><p>Creating Predix Cache and Predix Database as a Service are asnchronous paid services so it can take several minutes for the instances to be provisioned and available for use. There are parameters for you to override the default names and plans if you care about those settings.</p><p>If you are unfamiliar with GoTTY, please check out my post <a href="https://medium.com/@j12y/go-inside-the-container-34760e0bec1e">Go Inside the Container</a> to learn how you can setup a bash shell to work with redis-cli and psql. More importantly, you can use this bash shell to test any Python scripting you do when working with these services to help you develop faster. The PredixPy SDK primarily helps you establish the connection and everything else works the same way as the popular Python <a href="https://redislabs.com/lp/python-redis/">redis</a> and <a href="https://www.sqlalchemy.org/">sqlalchemy</a> libraries document.</p><h3>Event Hub</h3><p>If you prefer to listen, you can find out a bit more about Event Hub from this introductory video:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fn2u04GyQuf8%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dn2u04GyQuf8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fn2u04GyQuf8%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/60ca67dbacfb235b70541a71c6848716/href">https://medium.com/media/60ca67dbacfb235b70541a71c6848716/href</a></iframe><p>A common use case for the service is supporting Event-Oriented Architectures that have a Pub-Sub pattern coming from machines. If you are familiar with services like RabbitMQ <a href="https://forum.predix.io/questions/31276/whats-the-difference-between-event-hub-and-message.html?childToView=31284#answer-31284">some of the differences with Event Hub</a> come down to protocol and message contract.</p><p>You can get started by creating the service. You will need a UAA instance and client with appropriate scopes and authorities, but PredixPy handles those details.</p><pre>import predix.admin.app<br>admin = predix.admin.app.Manifest()<br>admin.create_uaa(&#39;admin-secret-ab&#39;)<br>admin.create_client(&#39;client-id-bc&#39;, &#39;client-secret-mb&#39;)<br>admin.create_eventhub(publish=True, subscribe=True)</pre><p>To subscribe to messages, you just listen and wait:</p><pre>import predix.app<br>app = predix.app.Manifest()<br>eh = app.get_eventhub()</pre><pre>for msg in eh.subscriber.subscribe():<br>    print(msg)</pre><p>To publish messages, you just queue it up and publish.</p><pre>import predix.app<br>app = predix.app.Manifest()<br>eh = app.get_eventhub()<br>for i in range(10, 0, -1):<br>    msg_id = str(i)<br>    msg_body = &#39;Final Countdown {}&#39;.format(msg_id)<br>    eh.publisher.add_message(msg_id, msg_body)</pre><pre>eh.publisher.publish_queue()</pre><p>Pretty straightforward eh?</p><h3>Cloud Foundry Automation</h3><p>PredixPy is primarily a client library for working with Predix APIs. Since Predix Services are running in a Cloud Foundry ecosystem, the scope of the SDK creeped into things like test automation and cloud foundry management.</p><p>You can run cf commands or use the predix cli to get work done, but I am always looking for ways to automate and don’t particularly like writing bash scripts.</p><p>Here’s a collection of fun CF tricks:</p><pre>import predix.admin.app<br>admin = predix.admin.app.Manifest()</pre><pre># Get a list of marketplace services<br>print(admin.space.get_services())</pre><pre># Create a space, name it something unique, then target it<br>import predix.admin.cf.spaces<br>predix.admin.cf.spaces.create_temp_space()<br>print(admin.space.name)</pre><pre># Invite my team to join the fun<br>admin.space.org.add_user(&#39;my-team@ge.com&#39;)<br>print(admin.space.org.get_users())</pre><p>It’s not a complete Cloud Foundry Client API but does offer some of the more common things that have come up as useful to automate.</p><h3>PredixPy 1.0</h3><p>That’s a taste of what’s new in PredixPy 1.0. There are still more services to be added and not every feature of the services is available yet, but it should still be able to get you through 80% of the most common use cases.</p><p>This is an open-source community SDK, so if you see something wrong — <a href="https://github.com/PredixDev/predixpy">raise an issue or fork and submit a PR</a>.</p><p>Hope that helps.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fac862672f51" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Poor-Man’s Control System]]></title>
            <link>https://j12y.medium.com/poor-mans-control-system-9ab9abd56e84?source=rss-f3c028e6e549------2</link>
            <guid isPermaLink="false">https://medium.com/p/9ab9abd56e84</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[predix]]></category>
            <category><![CDATA[industrial-controls]]></category>
            <category><![CDATA[internet-of-things]]></category>
            <dc:creator><![CDATA[Jayson DeLancey]]></dc:creator>
            <pubDate>Mon, 19 Mar 2018 01:04:15 GMT</pubDate>
            <atom:updated>2018-03-19T01:04:15.775Z</atom:updated>
            <content:encoded><![CDATA[<p>In the Industrial Internet of Things (IIoT), systems thinking is important. Systems manage flows of goods, chemicals, energy, and manufacturing processes that run the world. Unless you’ve spent some time in this Operations Technology (OT) world, you may not understand the purpose and mechanics behind control systems.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/241/1*ZyqzWVXbt5h7D3WoX_kHBw.jpeg" /></figure><p>From the recent book from Ryane Bohm, <a href="https://www.ge.com/digital/iiot-for-developers-ebook">Industrial IIoT for Developers</a>, a <strong>control system</strong> is described as an arrangement of physical components that is designed to regulate the equipment to which it’s attached. This can fall into a couple of categories. The first, <em>open-loop controls</em> are those that operate the same way regardless of conditions. An example given is that of a washing machine running for a set amount of time, regardless of whether it cleans the clothes or not. In the case of <em>closed-loop controls </em>we apply sensors and the control can take action based on sensor feedback, much like a thermostat does by sensing the temperature of the room and turning on/off the furnace or air conditioning unit.</p><p>The space gets more sophisticated as you begin experimenting with Programmable Logic Controllers (PLC), Supervisory Control and Data Aquisition (SCADA), Distributed Control Systems (DCS), and Data Historians that are commonly part of the system of an industrial process. The equipment involved tends to be expensive and mission critical so when rolling out new software and applications it is not always feasible to access these systems in a test environment where you can control the parameters and validate your app.</p><p>For this reason, I experimented recently with what could be considered a poor man’s control system. I’ve hacked together a control system for my Steam Engine Digital Twin using a <a href="http://www.belkin.com/us/F7C029-Belkin/p/P-F7C029">Belkin WeMo Insight Smart Plug</a>. This is not what we typically mean by control system nor appropriate for an industrial environment, but for under $50 it provides an accessible means to experiment and build up a POC.</p><h3>Ping</h3><p>Getting things setup is not without a few obstacles which I’m not going to cover at length here. You need to setup the WeMo Mobile App to communicate with your switch and update the software.</p><p>I began using a Python API provided in a BSD licensed open-source project called <a href="https://github.com/iancmcc/ouimeaux">ouimeaux</a> to communicate with the switch. You can install by simply running pip install ouimeaux and pip install ouimeaux[server]. While many industrial control systems may use something like modbus or OPC-UA, the Belkin devices use basic <a href="https://en.wikipedia.org/wiki/Universal_Plug_and_Play">UPnP</a> which make the devices discoverable by a server listening on the network.</p><p>Getting started, I create an environment and call start() and discover() which will create a UPnP server listening for messages to discover the devices communicating over the network. The list_switches() call should include the WeMo I configured in the app.</p><pre>import ouimeaux.environment</pre><pre># Setup UPnP server and listen for devices<br>env = ouimeaux.environment.Environment()<br>env.start()<br>env.discover()</pre><pre># Make sure we found the switch<br>if &#39;SteamControl&#39; not in env.devices:<br>    print(env.list_switches())<br>    raise ValueError(&quot;Unable to discover control system.&quot;)</pre><pre># Now we have access to our control<br>control = env.get_switch(&#39;SteamControl&#39;)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Zwqku-3d--27Z30W4YfZXA.png" /></figure><p>The Wemo switch is named <em>SteamControl</em> because I’m adding it to a project I’ve talked about at <a href="http://gluecon.com/">GlueCon</a> and other venues. I have a <a href="https://www.wilesco-shop.de/steam-engines/wilesco-steam-engine-d20.html">Wilesco D20 Steam Engine</a> that I refer to as my steam-powered data generator.</p><p><strong>Source: </strong><a href="https://www.wilesco.de/en/steam-engines.html"><strong>How a steam engine works</strong></a></p><p>The D20 unit is electric powered so I’m interested in learning about how much elecricity is needed to maintain pressure in the boiler and keep the machine running. I also want to respond to a situation where the pressure gets too high in the boiler to be able to shut-down power and let the system cool off or at the very least alert me to intervene and blow the whistle to stabilize the system.</p><h3>Basic Insight</h3><p>I have some basic control functions now over my light switch. I can find out what the current energy draw is, I can get an aggregate for the day or how long it has been enabled, and I can toggle it on or off.</p><pre># We have access to some metadata around electricity usage<br>print(&quot;current_power = &quot; + str(control.current_power))<br>print(&quot;today_kwh = &quot; + str(control.today_kwh))<br>print(&quot;today_on_time = &quot; + str(control.today_on_time))</pre><p>Mac Address, SSID, Serial Number, etc. are also useful features of the asset model for this particular device.</p><p>It is pretty easy and straightforward to send this data to Predix Time Series and Predix Asset by using the Predix Python SDK. You can find documentation on that library from the <a href="https://github.com/PredixDev/predixpy">PredixPy Github</a>.</p><h3>Big Picture</h3><p>The Control System is a closed-loop for providing a See-Think-Do response with milli-second level accuracy reliably in safety critical applications. The opportunity is to extract the sensor data from these Control Systems and aggregate it in the cloud where responsiveness is no longer a requirement. We can take advantage of distributed computing to apply machine learning / deep learning algorithms to help better understand and learn from the equipment for the types of insights we can use to optimize the control system and other operations in industrial environments. More about how I’m using this steam engine as an experiment in data analysis in another post.</p><p>Hope this little demonstration helps you think about the problem space, continue to learn about control systems, and maybe give the Predix Python SDK a try on your next project.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9ab9abd56e84" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>