<?xml version="1.0" ?>
<rss version="2.0">
<channel>
  <title>chamook.lol</title>
  <link>https://chamook.lol/</link>
  <description>Posts from chamook.lol</description>

<item>
  <title>An emacs macro to transform DTOs</title>
  <link>https://chamook.lol/emacs-macro-for-classes-to-records/</link>
  <description>
    &lt;div id="content" class="container"&gt;
    &lt;p&gt;
    I really like how emacs macros let me capture and replay my own stupid approaches to problems.
    &lt;/p&gt;
    
    &lt;p&gt;
    I had a bunch of DTO classes that looked like this:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-csharp"&gt;&lt;span style="color: #4c83ff; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #4c83ff; font-weight: bold;"&gt;class&lt;/span&gt; &lt;span style="color: #afd8af; font-weight: bold;"&gt;ThingContainer&lt;/span&gt;
    &lt;span style="color: #8b0000;"&gt;{&lt;/span&gt;
        &lt;span style="color: #006400;"&gt;[&lt;/span&gt;&lt;span style="color: #ff1493; font-weight: bold;"&gt;JsonPropertyName&lt;/span&gt;&lt;span style="color: #ff1493;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;"thing_one"&lt;/span&gt;&lt;span style="color: #ff1493;"&gt;)&lt;/span&gt;&lt;span style="color: #006400;"&gt;]&lt;/span&gt;
        &lt;span style="color: #4c83ff; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #afd8af; font-weight: bold;"&gt;string&lt;/span&gt; ThingOne &lt;span style="color: #006400;"&gt;{&lt;/span&gt; &lt;span style="color: #4c83ff; font-weight: bold;"&gt;get&lt;/span&gt;; &lt;span style="color: #4c83ff; font-weight: bold;"&gt;set&lt;/span&gt;; &lt;span style="color: #006400;"&gt;}&lt;/span&gt;
    
        &lt;span style="color: #006400;"&gt;[&lt;/span&gt;&lt;span style="color: #ff1493; font-weight: bold;"&gt;JsonPropertyName&lt;/span&gt;&lt;span style="color: #ff1493;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;"thing_two"&lt;/span&gt;&lt;span style="color: #ff1493;"&gt;)&lt;/span&gt;&lt;span style="color: #006400;"&gt;]&lt;/span&gt;
        &lt;span style="color: #4c83ff; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #afd8af; font-weight: bold;"&gt;string&lt;/span&gt; ThingTwo &lt;span style="color: #006400;"&gt;{&lt;/span&gt; &lt;span style="color: #4c83ff; font-weight: bold;"&gt;get&lt;/span&gt;; &lt;span style="color: #4c83ff; font-weight: bold;"&gt;set&lt;/span&gt;; &lt;span style="color: #006400;"&gt;}&lt;/span&gt;
    &lt;span style="color: #8b0000;"&gt;}&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    and I wanted to convert them into records like this:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-csharp"&gt;&lt;span style="color: #4c83ff; font-weight: bold;"&gt;public&lt;/span&gt; &lt;span style="color: #4c83ff; font-weight: bold;"&gt;sealed&lt;/span&gt; &lt;span style="color: #afd8af; font-weight: bold;"&gt;record&lt;/span&gt; &lt;span style="color: #ff1493; font-weight: bold;"&gt;ThingContainer&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;
        &lt;span style="color: #006400;"&gt;[&lt;/span&gt;property: &lt;span style="color: #ff1493; font-weight: bold;"&gt;JsonPropertyName&lt;/span&gt;&lt;span style="color: #ff1493;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;"thing_one"&lt;/span&gt;&lt;span style="color: #ff1493;"&gt;)&lt;/span&gt;&lt;span style="color: #006400;"&gt;]&lt;/span&gt; &lt;span style="color: #afd8af; font-weight: bold;"&gt;string&lt;/span&gt; ThingOne,
        &lt;span style="color: #006400;"&gt;[&lt;/span&gt;property: &lt;span style="color: #ff1493; font-weight: bold;"&gt;JsonPropertyName&lt;/span&gt;&lt;span style="color: #ff1493;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;"thing_two"&lt;/span&gt;&lt;span style="color: #ff1493;"&gt;)&lt;/span&gt;&lt;span style="color: #006400;"&gt;]&lt;/span&gt; &lt;span style="color: #afd8af; font-weight: bold;"&gt;string&lt;/span&gt; ThingTwo&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    I'm sure Visual Studio or Rider has a feature for doing that, but I am just a simple country emacs user so
    I used some find and replace commands, and made a macro so it was easy to repeat. This is all using evil mode
    and some very vim commands.
    &lt;/p&gt;
    
    &lt;p&gt;
    First off, change &lt;code&gt;class&lt;/code&gt; to &lt;code&gt;sealed record&lt;/code&gt;:
    &lt;/p&gt;
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-nil"&gt;:%s/class/sealed record
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    This is a change that was easy enough to apply to all the classes at once, so it doesn't need to be part of a macro.
    &lt;/p&gt;
    
    &lt;p&gt;
    Now to the fiddly bit, position the cursor on the opening curly boi and start a macro (&lt;code&gt;C-x (&lt;/code&gt; in my config)
    then do the following:
    &lt;/p&gt;
    
    &lt;p&gt;
    Select the whole body of the class
    &lt;/p&gt;
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-nil"&gt;V %
    &lt;/pre&gt;
    &lt;/div&gt;
    &lt;p&gt;
    Add the &lt;code&gt;property&lt;/code&gt; prefix to the attributes:
    &lt;/p&gt;
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-nil"&gt;:'&lt;,'&gt;s/JsonProperty/property: JsonProperty/
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    After each find/replace command the text is unselected so it needs to be selected again before running the next one.
    In this case, the cursor ends up on the last attribute, so moving down twice gets to the closing curly boi (&lt;code&gt;j j&lt;/code&gt;)
    then selecting everything is the same as before:
    &lt;/p&gt;
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-nil"&gt;V %
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    Remove &lt;code&gt;public&lt;/code&gt; from all the properties:
    &lt;/p&gt;
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-nil"&gt;:'&lt;,'&gt;s/public //
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    Select the whole class again by moving one line down &lt;code&gt;j&lt;/code&gt; and then pressing &lt;code&gt;V %&lt;/code&gt;
    &lt;/p&gt;
    
    &lt;p&gt;
    Remove the get and set, and the blank line as well:
    &lt;/p&gt;
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-nil"&gt;:'&lt;,'&gt;s/ { get.*\n/,/
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    Select the whole class again by pressing &lt;code&gt;V %&lt;/code&gt;
    &lt;/p&gt;
    
    &lt;p&gt;
    Remove the newline between the attributes and the properties:
    &lt;/p&gt;
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-nil"&gt;:'&lt;,'&gt;s/]\n */] /
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    Move to the beginning of the class &lt;code&gt;A&lt;/code&gt; to get to the end of the line &lt;code&gt;%&lt;/code&gt; to jump to the opening curly boi
    &lt;/p&gt;
    
    &lt;p&gt;
    &lt;code&gt;A&lt;/code&gt; to edit at the end of the line, then backspace twice to delete the curly boi and newline, replace it with &lt;code&gt;(&lt;/code&gt;,
    &lt;code&gt;esc&lt;/code&gt; to go back to normal mode after typing.
    &lt;/p&gt;
    
    &lt;p&gt;
    This change breaks the scope declaration so &lt;code&gt;%&lt;/code&gt; won't work for getting to the end of the block anymore,
    instead use &lt;code&gt;}&lt;/code&gt; to get to the next blank line, and &lt;code&gt;b&lt;/code&gt; jumps backwards to the trailing comma. Select that and the
    closing curly boi with &lt;code&gt;v e&lt;/code&gt; then &lt;code&gt;c&lt;/code&gt; to replace it, type &lt;code&gt;);&lt;/code&gt; as the last part of our record, then &lt;code&gt;esc&lt;/code&gt; for
    back to normal mode.
    &lt;/p&gt;
    
    &lt;p&gt;
    Finally &lt;code&gt;C-x )&lt;/code&gt; to finish recording the macro.
    &lt;/p&gt;
    
    &lt;p&gt;
    Now it can be used on all the other classes by moving the cursor to the right position and hitting &lt;code&gt;C-x e&lt;/code&gt;
    &lt;/p&gt;
    
    &lt;p&gt;
    Doing it this way let me work through the changes I wanted to make one at a time, and then have a simple command for all the
    other classes where I wanted to make the change 😃
    &lt;/p&gt;
    &lt;/div&gt;
    
  </description>
  <pubDate>Sun, 16 Feb 2025 15:30:01 +0200</pubDate>
  <guid>https://chamook.lol/emacs-macro-for-classes-to-records/</guid>
  </item>

<item>
  <title>Stop Pretending To Be Stupid</title>
  <link>https://chamook.lol/not-so-stupid/</link>
  <description>
    &lt;div id="content" class="container"&gt;
    &lt;p&gt;
    There's a tone in much of the writing that I have read about software development lately,
    a tone that insists that we &lt;i&gt;mustn't be too smart&lt;/i&gt; and &lt;i&gt;we shouldn't do clever things&lt;/i&gt; in case
    the creations we produce from applying our intellect become &lt;i&gt;too complex&lt;/i&gt; and thus
    &lt;i&gt;too difficult to maintain&lt;/i&gt;.
    &lt;/p&gt;
    
    &lt;p&gt;
    I don't like it.
    &lt;/p&gt;
    
    &lt;p&gt;
    There are indeed merits to reducing complexity where possible - simpler things do
    tend to be well&#x2026;simpler. However, I think this tendency to push away from complexity
    and away from doing something that is arbitrarily decreed as &lt;i&gt;too smart&lt;/i&gt; is harmful both to the
    process of creating software and to the software that is produced.
    &lt;/p&gt;
    
    &lt;p&gt;
    Complexity is inherent to software. Software should aid us in performing real world tasks,
    those tasks have a level of complexity. So in order to manage those tasks,
    &lt;a href="https://en.wikipedia.org/wiki/Complexity#The_law_of_requisite_complexity"&gt;the law of requisite complexity&lt;/a&gt; asserts that the software must be at least as complex. It is not
    unreasonable to design software such that it can only manage a subset of operations
    within a task - but this is an explicit choice that should have ramifications across the
    software making it clear where it's limits lie, and providing necessary feedback and
    information to allow humans to take over.
    &lt;/p&gt;
    
    &lt;p&gt;
    This attitude of avoiding &lt;i&gt;being clever&lt;/i&gt; extends to users as well. If we do not believe that
    the genius developer can handle complexity, our estimation of an end user is lower still.
    We do not expect that a lowly user could take over where the machine reaches its limit,
    and thus do not equip them to do so.
    &lt;/p&gt;
    
    &lt;div id="outline-container-org4ef72dd" class="outline-2"&gt;
    &lt;h2 id="org4ef72dd"&gt;Stupidly Building&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-org4ef72dd"&gt;
    &lt;p&gt;
    When we build software, we must consider what it is intended to do. A deeper understanding
    of the problem space allows us to create software that is correspondingly more able to
    provide assistance in solving that problem. Building software that is effective in a problem
    space also requires an understanding of the complexities in the software itself.
    &lt;/p&gt;
    
    &lt;p&gt;
    To reduce this overhead and to enable greater focus on the problem domain, we can learn
    development techniques that allow for more expressive code, or for more succinct handling
    of the required logic.
    &lt;/p&gt;
    
    &lt;p&gt;
    A quest for simplicity often stalls progress on both of these fronts. Problem spaces are not
    thoroughly explored, instead preferring to cleave to the happy path with the minimum
    amount of disruption from beginning to end. Software development is viewed in a similarly
    restricted fashion: more advanced techniques are never explored (despite their potential
    suitability for a problem space) and a lowest common denominator set of techniques is
    seen as an outer boundary.
    &lt;/p&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org5aed7ae" class="outline-3"&gt;
    &lt;h3 id="org5aed7ae"&gt;The Happy Path&lt;/h3&gt;
    &lt;div class="outline-text-3" id="text-org5aed7ae"&gt;
    &lt;p&gt;
    The happy path is a seductive proposition when starting on a new piece of software
    functionality. If we can focus just on what should happen when everything goes right
    then we can show speedy progress and everyone will be happy. But software has to
    operate in a world where everything doesn't always go as expected. Errors and outliers
    must be considered at some point, but continuing to work on them after showing a
    functioning system can easily be considered an unnecessary waste.
    &lt;/p&gt;
    
    &lt;p&gt;
    Avoiding errors at the start has more insidious ramifications than the obvious risk of
    the work to handle them being delayed. Defining a model in software that doesn't consider
    such outcomes can lead to a model that is incapable of handling them and difficult to
    modify such that it would be capable of dealing with them. If such a model becomes the
    source of truth for how a system should operate, it also hides any information about
    error states from any future developers. This causes a significant increase in the amount
    of work needed to even see the potential problems, never mind that needed to address
    them.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgc1c5056" class="outline-3"&gt;
    &lt;h3 id="orgc1c5056"&gt;Using this hammer has really simplified all my problems&lt;/h3&gt;
    &lt;div class="outline-text-3" id="text-orgc1c5056"&gt;
    &lt;p&gt;
    Code is the most malleable substance that we have available to work with. With it we
    can create and recreate systems of all sorts of shapes and sizes. This means that there
    are a great many tools and techniques that can be used in a many different programming
    paradigms from simple procedural scripts to total functional programming and everything
    else.
    &lt;/p&gt;
    
    &lt;p&gt;
    This wealth of knowledge ensures that for any given problem that software should help
    with, there is likely a technique that allows it to be represented clearly and worked with
    gracefully.
    &lt;/p&gt;
    
    &lt;p&gt;
    But in a quest for simplicity at all costs many tools and techniques are ignored or
    forbidden. We cannot adopt a new language/tool/framework/technique because we do
    not all understand it. This greatly limits the suitability of code that is produced to the
    problem at hand, and increases the chances that the complexities inherent in the problem
    will not properly be accommodated.
    &lt;/p&gt;
    
    &lt;p&gt;
    I could use a hammer to bang screws into place, but it would be more effective to use a
    screwdriver.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org6206c19" class="outline-2"&gt;
    &lt;h2 id="org6206c19"&gt;Stupid Software&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-org6206c19"&gt;
    &lt;p&gt;
    Whether or not software complexity is considered during the building of software, it is
    inevitably encountered during its use. Software that is unsuited to the task for which it was
    intended harms those who rely on using it.
    &lt;/p&gt;
    
    &lt;p&gt;
    Even software that works as intended can still embody a lack of faith in any users that
    disempowers them, removing tools that would enable them to work more effectively in
    favour of more &lt;i&gt;simplicity&lt;/i&gt;.
    &lt;/p&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org62e445c" class="outline-3"&gt;
    &lt;h3 id="org62e445c"&gt;Your Name is Invalid&lt;/h3&gt;
    &lt;div class="outline-text-3" id="text-org62e445c"&gt;
    &lt;p&gt;
    A frustrating flaw in many software systems is an encoding of rules about data that do not
    reflect the realities of that data. Software routinely tells users that their names are incorrect,
    their addresses cannot be found, their gender could only be one of two rigid options, or
    that they are performing a feat that is clearly impossible and could they just stop lying about
    it.
    &lt;/p&gt;
    
    &lt;p&gt;
    These deficiencies reflect a poor understanding of the data model on the part of the developers
    that seek to eschew the complexities of reality in favour of a simpler model. In many cases,
    they also show a missed opportunity for an even simpler solution - not collecting the data
    in the first place. But where data relating to humans is essential to the function of a system,
    it should be collected in a form that deals with the myriad complexities of human life.
    To do any less is to exclude the lived experiences of real people.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org5fa7e56" class="outline-3"&gt;
    &lt;h3 id="org5fa7e56"&gt;Dead Ends&lt;/h3&gt;
    &lt;div class="outline-text-3" id="text-org5fa7e56"&gt;
    &lt;p&gt;
    When software is the only method by which a task can be accomplished, it must always
    be possible to accomplish the task using the software. A poor model of the task and the
    data involved can lead to dead ends, where no further steps can be taken because data
    collected excludes all options to continue.
    &lt;/p&gt;
    
    &lt;p&gt;
    It is not unreasonable to allow software to fail in complex tasks, but allowing that failing
    software to become a barrier to completion of the task is unacceptable. Software should
    be capable of the tasks for which it is intended, and where it fails it must provide an
    alternative path for a user.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgff19584" class="outline-3"&gt;
    &lt;h3 id="orgff19584"&gt;Power(less) Users&lt;/h3&gt;
    &lt;div class="outline-text-3" id="text-orgff19584"&gt;
    &lt;p&gt;
    Even where software is capable of performing in its intended role, it may still lack flexibility
    to offer users alternative ways of solving a problem.
    &lt;/p&gt;
    
    &lt;p&gt;
    Making software easy to use is a noble goal. The mantra that "you can't hold it wrong" is a
    good one. However someone approaches software, it should seek to be accommodating to
    them and guide them through performing the tasks that they need to complete with it.
    But people learn and grow in capabilities. What is suitable for a novice who must learn how
    to operate a system, is often limiting and slow for someone who has performed the same
    task many times before.
    &lt;/p&gt;
    
    &lt;p&gt;
    Refusing to offer more advanced ways of working with a system robs them of the potential
    to learn more about it. It operates as a sort of lock in that prevents them from learning more
    general skills that could be transferred from task to task.
    &lt;/p&gt;
    
    &lt;p&gt;
    In these cases, simplicity can be good until it is no longer appropriate. Humans are capable
    of handling complexities, and software ought to allow them to do so.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org583b6b8" class="outline-2"&gt;
    &lt;h2 id="org583b6b8"&gt;TL;DR&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-org583b6b8"&gt;
    &lt;p&gt;
    Software can be complex, but pretending that people are incapable of handling complexity
    leads us to shy away from dealing with it and that causes problems down the line. Instead,
    we must address that complexity head-on (even if that requires us to learn new things) in
    order to build software that is fit for purpose and beneficial to those who use it.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
  </description>
  <pubDate>Fri, 06 Oct 2023 09:00:01 +0200</pubDate>
  <guid>https://chamook.lol/not-so-stupid/</guid>
  </item>

<item>
  <title>Business Value Isn't Real, Only Vibes Can Be Trusted</title>
  <link>https://chamook.lol/value-vs-vibes/</link>
  <description>
    &lt;div id="content" class="container"&gt;
    &lt;p&gt;
    When &lt;i&gt;Agile Influencers&lt;/i&gt; wade into attempting to answer the question of &lt;i&gt;what&lt;/i&gt; to make rather
    than simply &lt;i&gt;how&lt;/i&gt; to go about making it the concept of &lt;i&gt;Business Value&lt;/i&gt; is often invoked as the
    measurestick by which to judge competing options. Simply pick the option that will deliver the
    maximum amount of &lt;i&gt;Business Value&lt;/i&gt; and your project will surely be a success and your team
    will certainly be productive.
    &lt;/p&gt;
    
    &lt;p&gt;
    I do not believe this is correct. I believe that &lt;i&gt;Business Value&lt;/i&gt; is an ill-defined idea, a lie, an
    irrelevance, and most assuredly not something you should allow to encroach on your decision
    making if you are serious about your craft (assuming of course, that misery is not your craft).
    &lt;/p&gt;
    
    &lt;blockquote&gt;
    &lt;p&gt;
    Blessed are the key stakeholders, for they will achieve the product goal
    &lt;/p&gt;
    
    &lt;p&gt;
    The Book of Scrum 4:19 (NIV)
    &lt;/p&gt;
    &lt;/blockquote&gt;
    
    &lt;div id="outline-container-orgc75626d" class="outline-2"&gt;
    &lt;h2 id="orgc75626d"&gt;What is valuable to a business anyways?&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-orgc75626d"&gt;
    &lt;p&gt;
    Under capitalism a business exists to concentrate wealth into the possession of its owners by
    making money &lt;sup&gt;&lt;a id="fnr.1" class="footref" href="#fn.1" role="doc-backlink"&gt;1&lt;/a&gt;&lt;/sup&gt;. This can be a motivating system to spur innovation and the production of
    goods and the deliverance of services that greatly improve the lives of all those who can
    purchase them. It can also lead to a bunch of weird dudes exploiting their way into hoarding a
    massive amount of wealth that they can use on &lt;a href="https://www.youtube.com/watch?v=Q1AilPvC37c"&gt;meaningless days out&lt;/a&gt; and
    &lt;a href="https://www.theverge.com/2022/11/15/23460729/elon-musk-fire-twitter-engineers-dissent"&gt;being dicks to people at websites&lt;/a&gt;. So I think we could say that at best it's a &lt;i&gt;mixed bag&lt;/i&gt;.
    &lt;/p&gt;
    
    &lt;blockquote&gt;
    &lt;p&gt;
    It's cool and good that people suffer and die from preventable problems, because that means
    that the number representing my almost unimaginable wealth goes up
    &lt;/p&gt;
    
    &lt;p&gt;
    literally every billionaire
    &lt;/p&gt;
    &lt;/blockquote&gt;
    
    &lt;p&gt;
    The obvious answer then to the question of Business Value is that anything that would make
    money for a business is valuable. However, even for things that directly deal with income or
    outgoings it is not always easy to directly identify which changes will lead to the business
    retaining a greater share of capital than it currently does - and this uncertainty is only amplified
    as the relationship becomes more indirect. This uncertainty is not limited only to a risk of
    developments not providing any return, but also the risk of any change actively harming the
    current state of affairs leading to losses.
    &lt;/p&gt;
    
    &lt;p&gt;
    Even if it were possible for a business to predict what actions would lead to the best returns
    (that is, those that return the greatest amount of profit) it is not certain that this aligns with
    the best outcome for anyone connected to the business who wants something other than
    maximum profit. Consider these possible actions:
    &lt;/p&gt;
    
    &lt;ul class="org-ul"&gt;
    &lt;li&gt;a company fires many workers from its product team leading to savings on labour but the
    fired workers have now lost their employment, and the remaining team is left with more work
    to split among fewer members causing an increase in stess&lt;/li&gt;
    &lt;li&gt;adding extra data collection to an app allows a company to sell that user data to advertisers
    (or shadier organisations) which brings extra income for the company but worsens the user
    experience and doesn't fit with the ethics of the developers&lt;/li&gt;
    &lt;li&gt;rushing a new feature to &lt;i&gt;meet market demands&lt;/i&gt; means that there is no time to properly
    evaluate the impact on the userbase and it's implementation leads to abuse&lt;/li&gt;
    &lt;/ul&gt;
    
    &lt;p&gt;
    Each of these scenarios could include the business realising perceived business value, but the
    other negative effects make them the opposite of valuable to anyone with other values.
    &lt;/p&gt;
    
    &lt;p&gt;
    Business Value then is at best a vague uncertainty, and at worst actively harmful on a scale only
    limited to those things that the business can affect. Using this as a guide for what work should
    be done is not a responsible way to use people's labour.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgd8538df" class="outline-2"&gt;
    &lt;h2 id="orgd8538df"&gt;A business without value?&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-orgd8538df"&gt;
    &lt;p&gt;
    Fine. Ok. A business has to make a profit or it can't exist. Maybe that's not a sensible way of
    organising our whole society given the nightmarish things we've seen it lead to. But fine,
    given the current arrangement of things we'll accept this for now&lt;sup&gt;&lt;a id="fnr.2" class="footref" href="#fn.2" role="doc-backlink"&gt;2&lt;/a&gt;&lt;/sup&gt;.
    &lt;/p&gt;
    
    &lt;p&gt;
    But perhaps we can be a little bit more discerning than just blindly accepting the wild and
    unchecked pursuit of profit at all costs?
    &lt;/p&gt;
    
    &lt;blockquote&gt;
    &lt;p&gt;
    I did it all for the nookie
    &lt;/p&gt;
    
    &lt;p&gt;
    Fred Durst, proposing an alternative system of value
    &lt;/p&gt;
    &lt;/blockquote&gt;
    
    &lt;p&gt;
    To simply remove the worst negative aspects of the pursuit of business value, doesn't solve the
    other challenges of determining what would offer positive returns - we need to find an approach
    that allows us to gain some insight into what does. For that matter, we also need to figure out
    a way to navigate with work that might not be quite so cartoonishly villianous, but could still
    have an impact that we aren't comfortable with.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgb35602d" class="outline-2"&gt;
    &lt;h2 id="orgb35602d"&gt;How do we decide what's valuable?&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-orgb35602d"&gt;
    &lt;p&gt;
    We don't need to throw out all of agile at least, so we can start with working in small increments
    that we immediately make available to get fast feedback. But we are left needing a method of
    judging that feedback, and we also want to be able to judge our own work without needing to
    inflict it on our unsuspecting users. While the users may ultimately decide if we keep or revert a
    change, it is important that we can decide for ourselves which changes we want to focus on in
    the first place.
    &lt;/p&gt;
    
    &lt;p&gt;
    To this end, I think it is worth making a semi structured attempt to evaluate our own feelings
    about a potential change before, during, and after we make it. Because I am ageing and wish
    to cling to a semblance of my youth, I will call this a &lt;i&gt;Vibe Check&lt;sup&gt;&lt;a id="fnr.3" class="footref" href="#fn.3" role="doc-backlink"&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/i&gt;.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgab30166" class="outline-2"&gt;
    &lt;h2 id="orgab30166"&gt;Checking the Vibes&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-orgab30166"&gt;
    &lt;blockquote&gt;
    &lt;p&gt;
    Search your feelings, you know this code is bad
    &lt;/p&gt;
    
    &lt;p&gt;
    Darth Vader (@l33td4rth on github)
    &lt;/p&gt;
    &lt;/blockquote&gt;
    
    &lt;p&gt;
    I think it is important to start with a disclaimer that this is not merely intended to be a system of
    self gratification. We are bound by externalities, and the actions we take do affect others - so
    it is necessary to approach a process such as this with a clear understanding of what we aim to
    do and where the limits of our understanding may lie. If I am working on something that will
    impact people who have a significantly different life experience to my own it may fall outside of
    my own competence to evaluate the effects of my changes on those people - but as I do not
    wish to cause harm with my actions it would fall on me to learn about those impacts, this is best
    accomplished by having a person from that group as part of the team I work with so that they are
    constantly involved but if that is not available I can reach outside the team and use  the good ol'
    fallback of talking with people.
    &lt;/p&gt;
    
    &lt;p&gt;
    Assuming that we are working as part of a team that has reached some level of consensus on
    what types of aims we have, and that we have methods in place to gain additional context from
    outside groups should we need it - we can proceed.
    &lt;/p&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgbe4f48f" class="outline-3"&gt;
    &lt;h3 id="orgbe4f48f"&gt;Thinkin' about the future&lt;/h3&gt;
    &lt;div class="outline-text-3" id="text-orgbe4f48f"&gt;
    &lt;p&gt;
    Before we make a change or build a thing, let's take a moment to consider what it is we're aiming
    to do and if the thing we're doing furthers that goal. Consider that there are many options of things
    to do at any given time, so if there is controversy about an option it could well be safe to just punt
    on it for now, and review it again later if some people still think it's a good idea - sometimes timing
    is a factor, but it's not worth compromising our integrity for a chance at good timing. Overall our
    goal should be to be generally happy and comfortable with what we're making, and happy and
    comfortable with the impact it has - but bear in mind that if something is difficult to do because
    we're doing it the right way to ensure it has a more positive impact, then that is good and the type
    of comfort we ought to be sacrificing rather than taking the easy way out but having worse outcomes
    for people affected by the system.
    &lt;/p&gt;
    
    &lt;p&gt;
    I promised (semi-)structure so here are some sample questions to ask at this stage, but it's not a
    prescriptive list so feel free to use your own questions that I am sure are definitely better than the
    ones I came up with and you should totally feel good about them.
    &lt;/p&gt;
    
    &lt;ul class="org-ul"&gt;
    &lt;li&gt;Will this change let our users do more with the system?&lt;/li&gt;
    &lt;li&gt;Are we clarifying concepts in our domain with this change?&lt;/li&gt;
    &lt;li&gt;If we had this feature already, what kind of problems would it be causing for us?&lt;/li&gt;
    &lt;li&gt;Is there a simpler way to get the same benefit?&lt;/li&gt;
    &lt;li&gt;Does making this change prevent us from doing other things in the future?&lt;/li&gt;
    &lt;/ul&gt;
    
    &lt;p&gt;
    Note that these questions are a mix of things that relate to the product and user experience, and
    things that relate to implementation details. I think it is important that we explicitly consider both
    at each stage of this process but understand that it will be necessary to make trade-offs.
    Naturally we want to be thrilled about both aspects, but sometimes providing a feature that is
    beneficial to users will require implementation work that is frustrating or boring and conversely
    sometimes engineering a solution properly will limit features that can be made available. The
    important thing is to be aware of both of these aspects and ensure that we are not violating our
    own constraints on either side for the sake of the other. Or in other words, don't do evil things
    because the tech was cool, and don't refuse to do good things because the tech is boring.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org4f7d5ff" class="outline-3"&gt;
    &lt;h3 id="org4f7d5ff"&gt;Conciously doing&lt;/h3&gt;
    &lt;div class="outline-text-3" id="text-org4f7d5ff"&gt;
    &lt;p&gt;
    As work progresses on any given feature/change/iteration we will learn more about what it is
    we're making. Hopefully, any new information we discover will simply confirm that we made a
    fantastic choice to work on this particular thing and that will be that, but more likely we will be
    presented with questions and challenges about the implementation of what we're doing, and
    possibly we might even discover that give us pause about the impact of it.
    &lt;/p&gt;
    
    &lt;p&gt;
    We need to make space as we work to address this information when we discover it, because if
    it does have a significant impact on how we want to proceed with the work it will save us time,
    frustration, and effort to consider that impact as it is made rather than progressing along a bad
    course and making the costs of change higher. I am certain that by this point, you're brimming
    with ideas for questions to ask when you discover information as you build but I will include
    some samples here for completeness:
    &lt;/p&gt;
    
    &lt;ul class="org-ul"&gt;
    &lt;li&gt;Could we deliver a smaller version of this change to avoid technical challenges while still
    getting some benefit?&lt;/li&gt;
    &lt;li&gt;Should we expand the scope of this change so that it can properly deliver the value we wanted?&lt;/li&gt;
    &lt;li&gt;Can we reasonably delay this change to implement it in a better way, or should we focus on
    delivering the change now and change the way we implement it later?&lt;/li&gt;
    &lt;li&gt;[dramatically] Have we underestimated the impact of this change and should abandon it for
    now until we know it won't cause problems?&lt;/li&gt;
    &lt;li&gt;[less dramatically] Did we discover that this change won't be able to solve the problem that we
    wanted it to? Is it still worth implementing?&lt;/li&gt;
    &lt;/ul&gt;
    
    &lt;p&gt;
    These questions imply the possibility of significantly increasing the amount of work that we need
    to do, or significantly decreasing the amount of stuff we deliver&lt;sup&gt;&lt;a id="fnr.4" class="footref" href="#fn.4" role="doc-backlink"&gt;4&lt;/a&gt;&lt;/sup&gt; and this is often something
    that needs to be coordinated with other people. This potential for disruption when an expected
    timeline has been set is something that makes a lot of people uncomfortable but if we are to
    give a proper amount of respect and consideration to new information then it is to a degree
    unavoidable. It is important then to avoid conflict with people who might rely on our work, that
    we are clear up front about things that can happen during the process. Try where possible, to
    work with people on shared &lt;i&gt;goals&lt;/i&gt; rather than a specific &lt;i&gt;change&lt;/i&gt; or &lt;i&gt;feature&lt;/i&gt; - it is easier to
    let go of a feature when it becomes clear that it is not meeting your needs than when you expect
    it is the solution to your problems.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org1f0700f" class="outline-3"&gt;
    &lt;h3 id="org1f0700f"&gt;Spectating retroactively&lt;/h3&gt;
    &lt;div class="outline-text-3" id="text-org1f0700f"&gt;
    &lt;p&gt;
    Some things are never done. Whenever we deliver something we want to know how well it is
    actually received, how fit it turned out to be for its purpose, how it should impact our future
    changes, and if we learned anything from the process that should change the way we work or
    the questions we ask in the future.
    &lt;/p&gt;
    
    &lt;blockquote&gt;
    &lt;p&gt;
    Look upon my works, ye mighty, and tell me on a scale of 1 and 10 how likely you would be to
    recommend them to a friend
    &lt;/p&gt;
    
    &lt;p&gt;
    Ozymandias, King of NPS
    &lt;/p&gt;
    &lt;/blockquote&gt;
    
    &lt;p&gt;
    Releasing something new is exciting, it can be all too easy to become attached to what you have
    made and lose focus on what it was supposed to do, be on your guard against such feelings -
    remember the reasons that you do things, not only what you have done.
    &lt;/p&gt;
    
    &lt;p&gt;
    When something is out in the world and in use, it can be tempting to search for simple metrics
    that fit nicely onto a graph to evaluate how something was received - the graph is going up, so
    everything is good! Some metrics are good and useful, for example we know
    &lt;a href="https://www.nngroup.com/articles/response-times-3-important-limits/"&gt;how fast something should respond&lt;/a&gt; when people are working with it so we can track the
    response times of our own systems to see if they fall into line. Other metrics are less useful,
    if we really want to get a feel for how a change is working out in the world, we need to seek out
    qualitative information from people who actually use it - the ideal scenario being the opportunity
    to watch people use the system and then talk with them afterwards.
    &lt;/p&gt;
    
    &lt;p&gt;
    The questions that you ask to users should be different to those that you ask yourselves, the goal
    when talking to them is to discover how they use a system and why they did it in that particular way -
    this can often give insights into how it could better work with them to gain a desired result, but it
    can also provide things to consider about how you got here. The following are some examples of
    questions that we may want to ask ourselves:
    &lt;/p&gt;
    
    &lt;ul class="org-ul"&gt;
    &lt;li&gt;Did the results match our expectations?&lt;/li&gt;
    &lt;li&gt;Was our understanding of the problem domain complete?&lt;/li&gt;
    &lt;li&gt;How much information did we reveal while making something, and does that information change
    our expectations for the future?&lt;/li&gt;
    &lt;li&gt;Is there anything we learned during this that we didn't immediately act upon, but now we should
    do something with it?&lt;/li&gt;
    &lt;/ul&gt;
    
    &lt;p&gt;
    Asking questions at this stage is necessarily concerned with the past, and thus has some limited
    scope for what we can impact - but it also has the most concrete information about what actually
    happened that can serve to increase our confidence in future changes. Given a comparison between
    our initial expectations and our actual measured outcomes, we can see the impact of any of our
    earlier interventions and use discrepancies to guide any future changes we wish to make.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org6bbb545" class="outline-3"&gt;
    &lt;h3 id="org6bbb545"&gt;Rinse and Repeat&lt;/h3&gt;
    &lt;div class="outline-text-3" id="text-org6bbb545"&gt;
    &lt;p&gt;
    As described earlier, work on a system should proceed in small increments where possible such
    that we can pass through each of the stages above many times during the lifetime of a system. It
    is important both to maintain the process of asking questions as we go, guarding against the
    complacency that comes with repetition to ensure that we keep questioning what we are doing; and
    to evaluate the process itself to ensure that our ways of working do not guide us into producing things
    that go against our goals.
    &lt;/p&gt;
    
    &lt;p&gt;
    Like with learning another language, or trying to lift heavier weights this is a process that rewards
    consistent effort over a long time rather than a single burst of herculean exertion. As we produce
    more new things, and have more history to evaluate and draw lessons from we can improve our
    every step towards the future.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgb2ec9fb" class="outline-2"&gt;
    &lt;h2 id="orgb2ec9fb"&gt;What was all this about?&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-orgb2ec9fb"&gt;
    &lt;blockquote&gt;
    &lt;p&gt;
    I tried so hard, and got so far, but in the end I didn't hit my KPIs
    &lt;/p&gt;
    
    &lt;p&gt;
    Chester Bennington
    &lt;/p&gt;
    &lt;/blockquote&gt;
    
    &lt;p&gt;
    You have significant productive capacity, but you can only use it on a limited number of things.
    Those things should not be decided merely by profit, they should be your way of making the world
    better according to your own values and ethics. Ok fine, you don't really have to make things
    better, sometimes getting by is enough - but making things worse as you go isn't fine and you
    are responsible for stopping that from happening. In order to keep track of what you're doing and
    the impact that it's having you should be prepared to question things along the way, before, during,
    and after doing something. You also need to be prepared to deal with the ramifications of acting
    on the information you gained from those questions.
    &lt;/p&gt;
    
    &lt;p&gt;
    You get to decide these things, and you can produce great stuff - listen to the vibes, don't chase
    blindly after business value.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;div id="footnotes"&gt;
    &lt;h2 class="footnotes"&gt;Footnotes&lt;/h2&gt;
    &lt;div id="text-footnotes"&gt;
    
    &lt;div class="footdef"&gt;&lt;sup&gt;&lt;a id="fn.1" class="footnum" href="#fnr.1" role="doc-backlink"&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div class="footpara" role="doc-footnote"&gt;&lt;p class="footpara"&gt;
    I do realise that software development is undertaken in contexts other than that of for a business,
    but I can't write about everything. If you are in one of those other contexts, maybe this post is less
    relevant to you, or maybe it is a trove of brilliant insights - I guess the only way to find out is to read it.
    xoxoxo
    &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
    
    &lt;div class="footdef"&gt;&lt;sup&gt;&lt;a id="fn.2" class="footnum" href="#fnr.2" role="doc-backlink"&gt;2&lt;/a&gt;&lt;/sup&gt; &lt;div class="footpara" role="doc-footnote"&gt;&lt;p class="footpara"&gt;
    Should we accept this forever though? Send your answer on the side of a bottle filled
    with burning gasoline to your nearest billionaire's compound.
    &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
    
    &lt;div class="footdef"&gt;&lt;sup&gt;&lt;a id="fn.3" class="footnum" href="#fnr.3" role="doc-backlink"&gt;3&lt;/a&gt;&lt;/sup&gt; &lt;div class="footpara" role="doc-footnote"&gt;&lt;p class="footpara"&gt;
    Do not feel the need to inform me that this phrasing is outdated, I simply do not wish to know.
    &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
    
    &lt;div class="footdef"&gt;&lt;sup&gt;&lt;a id="fn.4" class="footnum" href="#fnr.4" role="doc-backlink"&gt;4&lt;/a&gt;&lt;/sup&gt; &lt;div class="footpara" role="doc-footnote"&gt;&lt;p class="footpara"&gt;
    They also imply the opposite of those, but less work and more stuff done are nice things
    so let's just enjoy when that happens eh? 🍹
    &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
    
    
    &lt;/div&gt;
    &lt;/div&gt;&lt;/div&gt;
    
  </description>
  <pubDate>Mon, 28 Nov 2022 00:00:01 +0100</pubDate>
  <guid>https://chamook.lol/value-vs-vibes/</guid>
  </item>

<item>
  <title>Using Indego Robot Mowers from Homey</title>
  <link>https://chamook.lol/indego-homey/</link>
  <description>
    &lt;div id="content" class="container"&gt;
    &lt;p&gt;
    My brother-in-law has a &lt;a href="https://www.bosch-diy.com/dk/da/haveredskaber/robotplaeneklippere"&gt;Bosch Indego&lt;/a&gt; robot mower that he wants to control via &lt;a href="https://homey.app/"&gt;Homey&lt;/a&gt;. There was no
    app readily available, but there is an API available that has several open source clients. I helped him create
    some blocks of &lt;a href="https://homey.app/en-us/app/com.athom.homeyscript/HomeyScript/"&gt;HomeyScript&lt;/a&gt; to call the API and integrate the mower into the rest of his smart home. The code
    here leans heavily on the work already done in the &lt;a href="https://github.com/zazaz-de/iot-device-bosch-indego-controller"&gt;Java Controller Application&lt;/a&gt; and in the
    &lt;a href="https://pypi.org/project/pyIndego/"&gt;pyIndego Python Library&lt;/a&gt;, especially the &lt;a href="https://github.com/zazaz-de/iot-device-bosch-indego-controller/blob/master/PROTOCOL.md"&gt;documentation of the protocol&lt;/a&gt;.
    &lt;/p&gt;
    
    &lt;div id="outline-container-org2eea2a4" class="outline-2"&gt;
    &lt;h2 id="org2eea2a4"&gt;Authentication&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-org2eea2a4"&gt;
    &lt;p&gt;
    Most requests in the API require a &lt;code&gt;contextId&lt;/code&gt; value, and to get one of those we first need to make a
    &lt;code&gt;POST&lt;/code&gt; request to the &lt;code&gt;/authenticate&lt;/code&gt; endpoint providing some details about the client as well as
    a &lt;code&gt;Basic&lt;/code&gt; authentication token.
    &lt;/p&gt;
    
    &lt;p&gt;
    The authentication token is built by base64 encoding a string comprised of your username and password
    separated by a colon. This can be done conveniently in most programming languages, such as javascript:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-js" id="org299053b"&gt;&lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; btoa&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;"username@email.com:secret-password"&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    As is, this will output the following (but don't forget to use your actual username and password if you want
    to connect to the API for real):
    &lt;/p&gt;
    
    &lt;pre class="example"&gt;
    dXNlcm5hbWVAZW1haWwuY29tOnNlY3JldC1wYXNzd29yZA==
    &lt;/pre&gt;
    
    &lt;p&gt;
    (Note that the above code sample won't actually work in HomeyScript, so you'll need to use a different approach
    if you want to generate the token as part of that)
    &lt;/p&gt;
    
    &lt;p&gt;
    With the token generated we can get a &lt;code&gt;contextId&lt;/code&gt; from the &lt;code&gt;/authenticate&lt;/code&gt; endpoint:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-http" id="org2ee571d"&gt;&lt;span style="color: #96CBFE;"&gt;POST&lt;/span&gt; &lt;span style="color: #ff1493;"&gt;https://api.indego.iot.bosch-si.com/api/v1/authenticate&lt;/span&gt;
    &lt;span style="color: #ff69b4;"&gt;Authorization&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;Basic dXNlcm5hbWVAZW1haWwuY29tOnNlY3JldC1wYXNzd29yZA==&lt;/span&gt;
    &lt;span style="color: #ff69b4;"&gt;Content-Type&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;application/json&lt;/span&gt;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"accept_tc_id"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;"202012"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"device"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;""&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"os_type"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Android"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"os_version"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"4.0"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"dvc_manuf"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"unknown"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"dvc_type"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"unknown"&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;}&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    The token generated previously is provided in the &lt;code&gt;Authorization&lt;/code&gt; header, while we can use sample data to
    populate most of the fields in the request. It is worth noting that the &lt;code&gt;accept_tc_id&lt;/code&gt; field value will likely
    need to be updated in the future if a new revision of the terms and conditions for the API are released.
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-http"&gt;HTTP/1.1 200 
    &lt;span style="color: #ff69b4;"&gt;Content-Type&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;application/json&lt;/span&gt;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"contextId"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"'3f2a9e8c-93cb-402e-a200-e325859f3ffe"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"userId"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"0a86dc31-7136-4009-9ef6-61ac4cab696e"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"alm_sn"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"000000000"&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;}&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    This provides us with the &lt;code&gt;contextId&lt;/code&gt; that is needed to make other requests.
    &lt;/p&gt;
    
    &lt;p&gt;
    Before making other requests we can make this in a HomeyScript function:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-js"&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;// &lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;pull values from the flow editor&lt;/span&gt;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;user&lt;/span&gt; = args&lt;span style="color: #8b0000;"&gt;[&lt;/span&gt;&lt;span style="color: #96CBFE;"&gt;0&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;]&lt;/span&gt;;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;pwd&lt;/span&gt; = args&lt;span style="color: #8b0000;"&gt;[&lt;/span&gt;&lt;span style="color: #96CBFE;"&gt;1&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;]&lt;/span&gt;;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;// &lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;btoa isn't available :(&lt;/span&gt;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;buffer&lt;/span&gt; = Buffer.from&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;user + &lt;span style="color: #61CE3C;"&gt;':'&lt;/span&gt; + pwd&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;headerData&lt;/span&gt; = buffer.toString&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;'base64'&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;authHeader&lt;/span&gt; = &lt;span style="color: #61CE3C;"&gt;'Basic '&lt;/span&gt; + headerData;
    
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;authRequestBody&lt;/span&gt; = &lt;span style="color: #8b0000;"&gt;{&lt;/span&gt;
        accept_tc_id: &lt;span style="color: #61CE3C;"&gt;"202012"&lt;/span&gt;,
        device: &lt;span style="color: #61CE3C;"&gt;""&lt;/span&gt;,
        os_type: &lt;span style="color: #61CE3C;"&gt;"Android"&lt;/span&gt;,
        os_version: &lt;span style="color: #61CE3C;"&gt;"4.0"&lt;/span&gt;,
        dvc_manuf: &lt;span style="color: #61CE3C;"&gt;"unknown"&lt;/span&gt;,
        dvc_type: &lt;span style="color: #61CE3C;"&gt;"unknown"&lt;/span&gt;
    &lt;span style="color: #8b0000;"&gt;}&lt;/span&gt;;
    
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;result&lt;/span&gt; = &lt;span style="color: #4c83ff;"&gt;await&lt;/span&gt; fetch&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;'https://api.indego.iot.bosch-si.com/api/v1/authenticate'&lt;/span&gt;, &lt;span style="color: #006400;"&gt;{&lt;/span&gt;
        method: &lt;span style="color: #61CE3C;"&gt;'POST'&lt;/span&gt;,
        body: JSON.stringify&lt;span style="color: #ff1493;"&gt;(&lt;/span&gt;authRequestBody&lt;span style="color: #ff1493;"&gt;)&lt;/span&gt;,
        headers: &lt;span style="color: #ff1493;"&gt;{&lt;/span&gt;
            &lt;span style="color: #61CE3C;"&gt;'Authorization'&lt;/span&gt;: authHeader,
            &lt;span style="color: #61CE3C;"&gt;'Content-Type'&lt;/span&gt;: &lt;span style="color: #61CE3C;"&gt;'application/json'&lt;/span&gt;
        &lt;span style="color: #ff1493;"&gt;}&lt;/span&gt;
    &lt;span style="color: #006400;"&gt;}&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;// &lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;fail for any error and return any error message we were given&lt;/span&gt;
    &lt;span style="color: #4c83ff;"&gt;if&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;!result.ok&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;{&lt;/span&gt;
        &lt;span style="color: #4c83ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #4c83ff;"&gt;new&lt;/span&gt; &lt;span style="color: #afd8af;"&gt;Error&lt;/span&gt;&lt;span style="color: #006400;"&gt;(&lt;/span&gt;result.statusText&lt;span style="color: #006400;"&gt;)&lt;/span&gt;;
    &lt;span style="color: #8b0000;"&gt;}&lt;/span&gt;
    
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;body&lt;/span&gt; = &lt;span style="color: #4c83ff;"&gt;await&lt;/span&gt; result.json&lt;span style="color: #8b0000;"&gt;()&lt;/span&gt;;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;// &lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;return just the context id because we don't care about the other values&lt;/span&gt;
    &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; body.contextId;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    The two &lt;code&gt;const&lt;/code&gt; values for &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;pwd&lt;/code&gt;  should be provided from the flow editor, and this will output
    the &lt;code&gt;contextId&lt;/code&gt; as a text value, that can then be passed to another function to do something.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org16cb325" class="outline-2"&gt;
    &lt;h2 id="org16cb325"&gt;Get Available Devices&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-org16cb325"&gt;
    &lt;p&gt;
    If you already know the serial number for your mower, you can skip this step and just use that to work with it
    directly. If you don't know the serial number or you have multiple mowers that you want to work with, there
    is an API endpoint that will list all the available devices:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-http"&gt;&lt;span style="color: #96CBFE;"&gt;GET&lt;/span&gt; &lt;span style="color: #ff1493;"&gt;https://api.indego.iot.bosch-si.com/api/v1/alms/&lt;/span&gt;
    x-im-context-id&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 3f2a9e8c-93cb-402e-a200-e325859f3ffe
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    Which will give a list containing the serial number and status code for the mowers connected to the account:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-http"&gt;HTTP/1.1 200
    &lt;span style="color: #ff69b4;"&gt;Content-Type&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;application/json&lt;/span&gt;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;[&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"alm_sn"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"000000000"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"alm_status"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 258
    &lt;span style="color: #8B8989; font-style: italic;"&gt;}&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;]&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    The serial number is then used to get more detailed information or to control the mower.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgc165d77" class="outline-2"&gt;
    &lt;h2 id="orgc165d77"&gt;Get Information About The Mower&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-orgc165d77"&gt;
    &lt;p&gt;
    Now we have the &lt;code&gt;contextId&lt;/code&gt; and the serial number of the mower we want to work with, we can make
    two different calls to get information about the mower.
    &lt;/p&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgd3cb5af" class="outline-3"&gt;
    &lt;h3 id="orgd3cb5af"&gt;State&lt;/h3&gt;
    &lt;div class="outline-text-3" id="text-orgd3cb5af"&gt;
    &lt;p&gt;
    First &lt;code&gt;/state&lt;/code&gt; will give information about the current state of the mower, we need to include the serial
    number of the mower we want to get information about in the url and the context id is provided as a header:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-http" id="orgcf4a5f7"&gt;&lt;span style="color: #96CBFE;"&gt;GET&lt;/span&gt; &lt;span style="color: #ff1493;"&gt;https://api.indego.iot.bosch-si.com/api/v1/alms/{serial-number}/state&lt;/span&gt;
    x-im-context-id&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 3f2a9e8c-93cb-402e-a200-e325859f3ffe
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    Which gives a response like this:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-http"&gt;HTTP/1.1 200
    &lt;span style="color: #ff69b4;"&gt;Content-Type&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;application/json&lt;/span&gt;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"state"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 258&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"enabled"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; true&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"map_update_available"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; true&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"mowed"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 98&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"mowmode"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 1&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"xPos"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 12&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"yPos"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 15&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"runtime"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"total"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
          &lt;span style="color: #61CE3C;"&gt;"operate"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 100000&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
          &lt;span style="color: #61CE3C;"&gt;"charge"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 30000
        &lt;span style="color: #8B8989; font-style: italic;"&gt;},&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"session"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
          &lt;span style="color: #61CE3C;"&gt;"operate"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 2&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
          &lt;span style="color: #61CE3C;"&gt;"charge"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 0
        &lt;span style="color: #8B8989; font-style: italic;"&gt;}&lt;/span&gt;
      &lt;span style="color: #8B8989; font-style: italic;"&gt;},&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"mapsvgcache_ts"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 1582506399367&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"svg_xPos"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 131&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"svg_yPos"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 111&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"config_change"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; false&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"mow_trig"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; false
    &lt;span style="color: #8B8989; font-style: italic;"&gt;}&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    The status code can be looked up in the following table that is a combination of data found in both the projects
    that I linked at the start of this post and some extra details that my brother-in-law figured out:
    &lt;/p&gt;
    
    &lt;table&gt;
    
    
    &lt;colgroup&gt;
    &lt;col  class="org-right"&gt;
    
    &lt;col  class="org-left"&gt;
    &lt;/colgroup&gt;
    &lt;thead&gt;
    &lt;tr&gt;
    &lt;th scope="col" class="org-right"&gt;Status Code&lt;/th&gt;
    &lt;th scope="col" class="org-left"&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
    &lt;tr&gt;
    &lt;td class="org-right"&gt;0&lt;/td&gt;
    &lt;td class="org-left"&gt;Reading Status&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;101&lt;/td&gt;
    &lt;td class="org-left"&gt;Docked&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;257&lt;/td&gt;
    &lt;td class="org-left"&gt;Charging&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;258&lt;/td&gt;
    &lt;td class="org-left"&gt;Docked&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;259&lt;/td&gt;
    &lt;td class="org-left"&gt;Docked - Software Update&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;260&lt;/td&gt;
    &lt;td class="org-left"&gt;Charging (Ran out of power)&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;261&lt;/td&gt;
    &lt;td class="org-left"&gt;Docked (Not 258 State)&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;262&lt;/td&gt;
    &lt;td class="org-left"&gt;Docked - Loading Map&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;263&lt;/td&gt;
    &lt;td class="org-left"&gt;Docked -Saving Map&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;266&lt;/td&gt;
    &lt;td class="org-left"&gt;Leaving Dock&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;512&lt;/td&gt;
    &lt;td class="org-left"&gt;Mowing&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;513&lt;/td&gt;
    &lt;td class="org-left"&gt;Mowing&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;514&lt;/td&gt;
    &lt;td class="org-left"&gt;Relocalising&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;515&lt;/td&gt;
    &lt;td class="org-left"&gt;Loading map&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;516&lt;/td&gt;
    &lt;td class="org-left"&gt;Learning lawn&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;517&lt;/td&gt;
    &lt;td class="org-left"&gt;Paused&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;518&lt;/td&gt;
    &lt;td class="org-left"&gt;Border cut&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;519&lt;/td&gt;
    &lt;td class="org-left"&gt;Idle in lawn&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;520&lt;/td&gt;
    &lt;td class="org-left"&gt;Mowing&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;521&lt;/td&gt;
    &lt;td class="org-left"&gt;Mowing&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;522&lt;/td&gt;
    &lt;td class="org-left"&gt;Mowing&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;523&lt;/td&gt;
    &lt;td class="org-left"&gt;Spot Mow&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;524&lt;/td&gt;
    &lt;td class="org-left"&gt;Mow without Docking Station&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;525&lt;/td&gt;
    &lt;td class="org-left"&gt;Mowing&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;768&lt;/td&gt;
    &lt;td class="org-left"&gt;Mowing&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;769&lt;/td&gt;
    &lt;td class="org-left"&gt;Returning to Dock&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;770&lt;/td&gt;
    &lt;td class="org-left"&gt;Returning to Dock&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;771&lt;/td&gt;
    &lt;td class="org-left"&gt;Returning to Dock - Battery low&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;772&lt;/td&gt;
    &lt;td class="org-left"&gt;Returning to dock - Calendar timeslot ended&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;773&lt;/td&gt;
    &lt;td class="org-left"&gt;Returning to dock - Battery temp range&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;774&lt;/td&gt;
    &lt;td class="org-left"&gt;Returning to dock&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;775&lt;/td&gt;
    &lt;td class="org-left"&gt;Returning to dock - Lawn complete&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;776&lt;/td&gt;
    &lt;td class="org-left"&gt;Returning to dock - Relocalising&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;1005&lt;/td&gt;
    &lt;td class="org-left"&gt;Mowing&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;1025&lt;/td&gt;
    &lt;td class="org-left"&gt;Diagnostic mode&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;1026&lt;/td&gt;
    &lt;td class="org-left"&gt;End of life&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;1027&lt;/td&gt;
    &lt;td class="org-left"&gt;Service Requesting Status&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;1038&lt;/td&gt;
    &lt;td class="org-left"&gt;Mower immobilized&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;1281&lt;/td&gt;
    &lt;td class="org-left"&gt;Software update&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;1537&lt;/td&gt;
    &lt;td class="org-left"&gt;Stuck&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;64513&lt;/td&gt;
    &lt;td class="org-left"&gt;Sleeping (Docked)&lt;/td&gt;
    &lt;/tr&gt;
    
    &lt;tr&gt;
    &lt;td class="org-right"&gt;99999&lt;/td&gt;
    &lt;td class="org-left"&gt;Offline&lt;/td&gt;
    &lt;/tr&gt;
    &lt;/tbody&gt;
    &lt;/table&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org2c9d890" class="outline-3"&gt;
    &lt;h3 id="org2c9d890"&gt;Operating Data&lt;/h3&gt;
    &lt;div class="outline-text-3" id="text-org2c9d890"&gt;
    &lt;p&gt;
    And then &lt;code&gt;/operatingData&lt;/code&gt; which can provide more detailed information for some properties, again
    including the serial number in the url and the context id as a header:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-http" id="org7b60ebd"&gt;&lt;span style="color: #96CBFE;"&gt;GET&lt;/span&gt; &lt;span style="color: #ff1493;"&gt;https://api.indego.iot.bosch-si.com/api/v1/alms/{serial number}/operatingData&lt;/span&gt;
    x-im-context-id&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 3f2a9e8c-93cb-402e-a200-e325859f3ffe
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    In a response that looks like this:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-http"&gt;HTTP/1.1 200 
    
    &lt;span style="color: #ff69b4;"&gt;Content-Type&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;application/json
    &lt;/span&gt;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"runtime"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"total"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
          &lt;span style="color: #61CE3C;"&gt;"operate"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 100000&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
          &lt;span style="color: #61CE3C;"&gt;"charge"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 35002
        &lt;span style="color: #8B8989; font-style: italic;"&gt;},&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"session"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
          &lt;span style="color: #61CE3C;"&gt;"operate"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 0&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
          &lt;span style="color: #61CE3C;"&gt;"charge"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 0
        &lt;span style="color: #8B8989; font-style: italic;"&gt;}&lt;/span&gt;
      &lt;span style="color: #8B8989; font-style: italic;"&gt;},&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"battery"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"voltage"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 7.0&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"cycles"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 0&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"discharge"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; -0.1&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"ambient_temp"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 23&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"battery_temp"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 23&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"percent"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 70
      &lt;span style="color: #8B8989; font-style: italic;"&gt;},&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"garden"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"id"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 1&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"name"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 1&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"signal_id"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 3&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"size"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 157&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"inner_bounds"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 0&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"cuts"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 0&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"runtime"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 100000&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"charge"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 35002&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"bumps"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 281&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"stops"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 90&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"last_mow"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 3&lt;span style="color: #8B8989; font-style: italic;"&gt;,&lt;/span&gt;
        &lt;span style="color: #61CE3C;"&gt;"map_cell_size"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 120
      &lt;span style="color: #8B8989; font-style: italic;"&gt;},&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"hmiKeys"&lt;/span&gt; &lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 12019
    &lt;span style="color: #8B8989; font-style: italic;"&gt;}&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgbfd3695" class="outline-3"&gt;
    &lt;h3 id="orgbfd3695"&gt;HomeyScript&lt;/h3&gt;
    &lt;div class="outline-text-3" id="text-orgbfd3695"&gt;
    &lt;p&gt;
    Knowing how these requests and responses look, we can make useful HomeyScript functions so we could
    display the information somewhere or include it as part of a flow.
    &lt;/p&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org04148fc" class="outline-4"&gt;
    &lt;h4 id="org04148fc"&gt;Get Status&lt;/h4&gt;
    &lt;div class="outline-text-4" id="text-org04148fc"&gt;
    &lt;p&gt;
    Query the state endpoint and return the status converted to a human readable string:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-js"&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;// &lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;pull values from the flow editor&lt;/span&gt;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;contextId&lt;/span&gt; = args&lt;span style="color: #8b0000;"&gt;[&lt;/span&gt;&lt;span style="color: #96CBFE;"&gt;0&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;]&lt;/span&gt;;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;serialNumber&lt;/span&gt; = args&lt;span style="color: #8b0000;"&gt;[&lt;/span&gt;&lt;span style="color: #96CBFE;"&gt;1&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;]&lt;/span&gt;;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;// &lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;get the current state&lt;/span&gt;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;result&lt;/span&gt; = &lt;span style="color: #4c83ff;"&gt;await&lt;/span&gt; fetch&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;'https://api.indego.iot.bosch-si.com/api/v1/alms/'&lt;/span&gt; + serialNumber + &lt;span style="color: #61CE3C;"&gt;'/state'&lt;/span&gt;, &lt;span style="color: #006400;"&gt;{&lt;/span&gt;
        method: &lt;span style="color: #61CE3C;"&gt;'GET'&lt;/span&gt;,
        headers: &lt;span style="color: #ff1493;"&gt;{&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;'x-im-context-id'&lt;/span&gt;: contextId &lt;span style="color: #ff1493;"&gt;}&lt;/span&gt;
    &lt;span style="color: #006400;"&gt;}&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;;
    
    &lt;span style="color: #4c83ff;"&gt;if&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;!result.ok&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;{&lt;/span&gt;
        &lt;span style="color: #4c83ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #4c83ff;"&gt;new&lt;/span&gt; &lt;span style="color: #afd8af;"&gt;Error&lt;/span&gt;&lt;span style="color: #006400;"&gt;(&lt;/span&gt;result.statusText&lt;span style="color: #006400;"&gt;)&lt;/span&gt;;
    &lt;span style="color: #8b0000;"&gt;}&lt;/span&gt;
    
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;body&lt;/span&gt; = &lt;span style="color: #4c83ff;"&gt;await&lt;/span&gt; result.json&lt;span style="color: #8b0000;"&gt;()&lt;/span&gt;;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;// &lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;convert the status code to human readable text&lt;/span&gt;
    &lt;span style="color: #4c83ff;"&gt;switch&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;body.state&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;{&lt;/span&gt;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;0&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Reading status"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;257&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Charging"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;258&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Docked"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;259&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Docked - Software update"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;260&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Docked (Ran out of Power)"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;261&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Docked (not 258 State)"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;262&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Docked - Loading map"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;263&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Docked - Saving map"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;266&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Leaving dock"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;513&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Mowing"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;514&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Relocalising"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;515&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Loading map"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;516&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Learning lawn"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;517&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Paused"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;518&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Border cut"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;519&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Idle in lawn"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;523&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Spot Mow"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;524&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Mow without Docking Station"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;769&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Returning to Dock"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;770&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Returning to Dock"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;771&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Returning to Dock - Battery low"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;772&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Returning to dock - Calendar timeslot ended"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;773&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Returning to dock - Battery temp range"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;774&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Returning to dock"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;775&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Returning to dock - Lawn complete"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;776&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Returning to dock - Relocalising"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;1005&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Mowing"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;1025&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Diagnostic mode"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;1026&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"End of life"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;1027&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Service Requesting Status"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;1038&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Mower immobilized"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;1281&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Software update"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;1537&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Stuck"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;64513&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Sleeping (Docked)"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;case&lt;/span&gt; &lt;span style="color: #96CBFE;"&gt;99999&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"Offline"&lt;/span&gt;;
        &lt;span style="color: #4c83ff;"&gt;default&lt;/span&gt;: &lt;span style="color: #4c83ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #4c83ff;"&gt;new&lt;/span&gt; &lt;span style="color: #afd8af;"&gt;Error&lt;/span&gt;&lt;span style="color: #006400;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;"Unknown state"&lt;/span&gt; + body.state&lt;span style="color: #006400;"&gt;)&lt;/span&gt;;
    &lt;span style="color: #8b0000;"&gt;}&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org6e3d2a6" class="outline-4"&gt;
    &lt;h4 id="org6e3d2a6"&gt;Get Battery Percentage&lt;/h4&gt;
    &lt;div class="outline-text-4" id="text-org6e3d2a6"&gt;
    &lt;p&gt;
    Query the operating data and return only the battery percentage value, this can easily be modified to return
    other values instead:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-js"&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;// &lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;pull values from the flow editor&lt;/span&gt;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;contextId&lt;/span&gt; = args&lt;span style="color: #8b0000;"&gt;[&lt;/span&gt;&lt;span style="color: #96CBFE;"&gt;0&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;]&lt;/span&gt;;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;serialNumber&lt;/span&gt; = args&lt;span style="color: #8b0000;"&gt;[&lt;/span&gt;&lt;span style="color: #96CBFE;"&gt;1&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;]&lt;/span&gt;;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;// &lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;get operating data&lt;/span&gt;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;result&lt;/span&gt; = &lt;span style="color: #4c83ff;"&gt;await&lt;/span&gt; fetch&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;'https://api.indego.iot.bosch-si.com/api/v1/alms/'&lt;/span&gt; + serialNumber + &lt;span style="color: #61CE3C;"&gt;'/operatingData'&lt;/span&gt;, &lt;span style="color: #006400;"&gt;{&lt;/span&gt;
        method: &lt;span style="color: #61CE3C;"&gt;'GET'&lt;/span&gt;,
        headers: &lt;span style="color: #ff1493;"&gt;{&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;'x-im-context-id'&lt;/span&gt;: contextId &lt;span style="color: #ff1493;"&gt;}&lt;/span&gt;
    &lt;span style="color: #006400;"&gt;}&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;;
    
    &lt;span style="color: #4c83ff;"&gt;if&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;!result.ok&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;{&lt;/span&gt;
        &lt;span style="color: #4c83ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #4c83ff;"&gt;new&lt;/span&gt; &lt;span style="color: #afd8af;"&gt;Error&lt;/span&gt;&lt;span style="color: #006400;"&gt;(&lt;/span&gt;result.statusText&lt;span style="color: #006400;"&gt;)&lt;/span&gt;;
    &lt;span style="color: #8b0000;"&gt;}&lt;/span&gt;
    
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;body&lt;/span&gt; = &lt;span style="color: #4c83ff;"&gt;await&lt;/span&gt; result.json&lt;span style="color: #8b0000;"&gt;()&lt;/span&gt;;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;//&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;return battery percentage&lt;/span&gt;
    &lt;span style="color: #4c83ff;"&gt;return&lt;/span&gt; body.battery.percent;
    &lt;/pre&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org7c94378" class="outline-2"&gt;
    &lt;h2 id="org7c94378"&gt;Control the Mower&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-org7c94378"&gt;
    &lt;p&gt;
    With code in place to authenticate with the API and retrieve information about the mower it is quite
    straightforward to control the mower. We just need to make a &lt;code&gt;PUT&lt;/code&gt; request to the &lt;code&gt;/state&lt;/code&gt; endpoint
    with the desired state command:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-http"&gt;&lt;span style="color: #96CBFE;"&gt;PUT&lt;/span&gt; &lt;span style="color: #ff1493;"&gt;https://api.indego.iot.bosch-si.com/api/v1/alms/{serial number}/state&lt;/span&gt;
    x-im-context-id&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; 3f2a9e8c-93cb-402e-a200-e325859f3ffe
    content-type&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; application/json
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;{&lt;/span&gt;
      &lt;span style="color: #61CE3C;"&gt;"state"&lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;:&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"mow"&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;}&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    We can issue a &lt;code&gt;mow&lt;/code&gt;  command to start the mower, and a &lt;code&gt;returnToDock&lt;/code&gt; command to stop it and have it
    go back to the dock.
    &lt;/p&gt;
    
    &lt;p&gt;
    In HomeyScript this can be done like so:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-js"&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;// &lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;pull values from the flow editor&lt;/span&gt;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;contextId&lt;/span&gt; = args&lt;span style="color: #8b0000;"&gt;[&lt;/span&gt;&lt;span style="color: #96CBFE;"&gt;0&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;]&lt;/span&gt;;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;serialNumber&lt;/span&gt; = args&lt;span style="color: #8b0000;"&gt;[&lt;/span&gt;&lt;span style="color: #96CBFE;"&gt;1&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;]&lt;/span&gt;;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;// &lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;send the request to the api&lt;/span&gt;
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;body&lt;/span&gt; = &lt;span style="color: #8b0000;"&gt;{&lt;/span&gt;
        state: &lt;span style="color: #61CE3C;"&gt;"mow"&lt;/span&gt;
    &lt;span style="color: #8b0000;"&gt;}&lt;/span&gt;;
    
    &lt;span style="color: #4c83ff;"&gt;const&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;result&lt;/span&gt; = &lt;span style="color: #4c83ff;"&gt;await&lt;/span&gt; fetch&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;'https://api.indego.iot.bosch-si.com/api/v1/alms/'&lt;/span&gt; + serialNumber + &lt;span style="color: #61CE3C;"&gt;'/state'&lt;/span&gt;, &lt;span style="color: #006400;"&gt;{&lt;/span&gt;
        method: &lt;span style="color: #61CE3C;"&gt;'PUT'&lt;/span&gt;,
        body: JSON.stringify&lt;span style="color: #ff1493;"&gt;(&lt;/span&gt;body&lt;span style="color: #ff1493;"&gt;)&lt;/span&gt;,
        headers: &lt;span style="color: #ff1493;"&gt;{&lt;/span&gt;
            &lt;span style="color: #61CE3C;"&gt;'x-im-context-id'&lt;/span&gt;: contextId,
            &lt;span style="color: #61CE3C;"&gt;'Content-Type'&lt;/span&gt;: &lt;span style="color: #61CE3C;"&gt;'application/json'&lt;/span&gt;
        &lt;span style="color: #ff1493;"&gt;}&lt;/span&gt;
    &lt;span style="color: #006400;"&gt;}&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;;
    
    &lt;span style="color: #4c83ff;"&gt;if&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;!result.ok&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;{&lt;/span&gt;
        &lt;span style="color: #4c83ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #4c83ff;"&gt;new&lt;/span&gt; &lt;span style="color: #afd8af;"&gt;Error&lt;/span&gt;&lt;span style="color: #006400;"&gt;(&lt;/span&gt;result.statusText&lt;span style="color: #006400;"&gt;)&lt;/span&gt;;
    &lt;span style="color: #8b0000;"&gt;}&lt;/span&gt;
    
    &lt;span style="color: #8B8989; font-style: italic;"&gt;// &lt;/span&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;this doesn't return a body, so as long as it didn't fail it should be good&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgbd27984" class="outline-2"&gt;
    &lt;h2 id="orgbd27984"&gt;Putting it together&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-orgbd27984"&gt;
    &lt;p&gt;
    The code snippets in this post can be added to HomeyScript cards in the flow editor, and you can link up your
    robot mower to anything else controlled by Homey.
    &lt;/p&gt;
    
    &lt;p&gt;
    The screenshot below shows examples of controlling the mower with a virtual device, and monitoring the
    battery percentage with a virtual sensor.
    &lt;/p&gt;
    
    
    &lt;figure id="org878b8c8"&gt;
    &lt;img src="./annotated-flow.png" alt="A screenshot of the Homey flow editor showing some ways of integrating the code from this post"&gt;
    
    &lt;/figure&gt;
    
    &lt;p&gt;
    Happy Automating!
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
  </description>
  <pubDate>Fri, 26 Aug 2022 00:00:01 +0100</pubDate>
  <guid>https://chamook.lol/indego-homey/</guid>
  </item>

<item>
  <title>Literate Programming with Org Mode 🦄 </title>
  <link>https://chamook.lol/literate-programming-with-org/</link>
  <description>
    &lt;div id="content" class="container"&gt;
    &lt;p&gt;
    Recently I've been writing &lt;a href="https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview?tabs=bicep"&gt;bicep&lt;/a&gt; for provisioning Azure services, the intent was to create a reusable template that could provision
    different services for different projects. Having never worked with bicep before I wanted to ensure I wrote good documentation that I
    could refer back to later, and decided to try out &lt;a href="https://orgmode.org/"&gt;Org Mode&lt;/a&gt; for its literate programming features to ensure that I kept the documentation
    in sync with the code.
    &lt;/p&gt;
    
    &lt;div id="outline-container-org2e9ad86" class="outline-2"&gt;
    &lt;h2 id="org2e9ad86"&gt;Structured Code&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-org2e9ad86"&gt;
    &lt;p&gt;
    Basic org syntax is a lot like markdown but using different special characters (&lt;code&gt;/&lt;/code&gt; for italics instead of &lt;code&gt;_&lt;/code&gt; etc) but a more significant
    difference is the approach of using structural blocks for source code. Markdown uses &lt;code&gt;```&lt;/code&gt; to denote a block of code, and some
    processors (like github's) can take a language argument (e.g. &lt;code&gt;``` csharp&lt;/code&gt;) to provide syntax highlighting. Org uses comparitively
    clunky looking &lt;code&gt;#+begin_src&lt;/code&gt; and &lt;code&gt;#+end_src&lt;/code&gt; markers to surround code blocks, but it provides a much richer feature set for them.
    &lt;/p&gt;
    
    &lt;p&gt;
    Code blocks take a language parameter just like the one some markdown processors provide, but within emacs this provides access to
    features from the language mode that you would use when editing a file of that type like syntax highlighting and autocompletion. 😀
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgcd16a31" class="outline-2"&gt;
    &lt;h2 id="orgcd16a31"&gt;Execution&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-orgcd16a31"&gt;
    &lt;p&gt;
    For some languages, it is also possible to execute the code directly inside the org file and have any output placed in a results block
    similar to &lt;a href="https://jupyter.org/try-jupyter/lab/"&gt;Jupyter Notebooks&lt;/a&gt;.
    &lt;/p&gt;
    
    &lt;p&gt;
    A javascript block with this header line:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-org"&gt;#+begin_src js :results output replace :wrap src json
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    And this javascript code:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-js" id="orgd48066c"&gt;fetch&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;'https://jsonplaceholder.typicode.com/todos/2'&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;
      .then&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;x =&gt; x.json&lt;span style="color: #006400;"&gt;()&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;
      .then&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;x =&gt; console.log&lt;span style="color: #006400;"&gt;(&lt;/span&gt;x&lt;span style="color: #006400;"&gt;)&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    Executing that code block will output a results section that wraps the result in a json source block:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-json"&gt;&lt;span style="color: #8b0000;"&gt;{&lt;/span&gt;
      userId: &lt;span style="color: #96CBFE;"&gt;1&lt;/span&gt;,
      id: &lt;span style="color: #96CBFE;"&gt;2&lt;/span&gt;,
      title: 'quis ut nam facilis et officia qui',
      completed: &lt;span style="color: #96CBFE;"&gt;false&lt;/span&gt;
    &lt;span style="color: #8b0000;"&gt;}&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    
    &lt;p&gt;
    But code in org files isn't limited to staying within the file, with &lt;code&gt;org-babel-tangle&lt;/code&gt; you can create code files from your documentation.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org80a784f" class="outline-2"&gt;
    &lt;h2 id="org80a784f"&gt;Tangling&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-org80a784f"&gt;
    &lt;p&gt;
    By adding &lt;code&gt;:tangle&lt;/code&gt; and a filename to the start of a block, you can output code from an org documentation file into a file that only
    contains code, and can even be part of a whole coding project.
    &lt;/p&gt;
    
    &lt;p&gt;
    Using &lt;code&gt;M-x org-babel-tangle&lt;/code&gt; from within emacs on a file containing a block like this:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-org"&gt;
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+begin_src csharp :tangle SampleClass.cs&lt;/span&gt;
    &lt;span style="color: #4c83ff; background-color: #383838;"&gt;namespace&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #ff69b4; background-color: #383838;"&gt;Chamook&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;.&lt;/span&gt;&lt;span style="color: #ff69b4; background-color: #383838;"&gt;Sample&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;;&lt;/span&gt;
    
    &lt;span style="color: #4c83ff; background-color: #383838;"&gt;public&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;sealed&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;class&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #afd8af; background-color: #383838;"&gt;SampleClass&lt;/span&gt;
    &lt;span style="color: #8b0000; background-color: #383838;"&gt;{&lt;/span&gt;
    &lt;span style="background-color: #383838;"&gt;    &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;public&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #afd8af; background-color: #383838;"&gt;string&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #ff69b4; background-color: #383838;"&gt;Name&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;{&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;get&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;; &lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;}&lt;/span&gt;
    
    &lt;span style="background-color: #383838;"&gt;    &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;public&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #afd8af; background-color: #383838;"&gt;void&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #ff1493; background-color: #383838;"&gt;Greet&lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;()&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; =&gt; Console.&lt;/span&gt;&lt;span style="color: #ff1493; background-color: #383838;"&gt;WriteLine&lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;(&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;$&lt;/span&gt;&lt;span style="color: #61CE3C; background-color: #383838;"&gt;"Hello, {Name}"&lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;)&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;;&lt;/span&gt;
    &lt;span style="color: #8b0000; background-color: #383838;"&gt;}&lt;/span&gt;
    
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+end_src&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    Will output a file called &lt;code&gt;SampleClass.cs&lt;/code&gt; with the code as contents:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-csharp"&gt;&lt;span style="color: #4c83ff;"&gt;namespace&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;Chamook&lt;/span&gt;.&lt;span style="color: #ff69b4;"&gt;Sample&lt;/span&gt;;
    
    &lt;span style="color: #4c83ff;"&gt;public&lt;/span&gt; &lt;span style="color: #4c83ff;"&gt;sealed&lt;/span&gt; &lt;span style="color: #4c83ff;"&gt;class&lt;/span&gt; &lt;span style="color: #afd8af;"&gt;SampleClass&lt;/span&gt;
    &lt;span style="color: #8b0000;"&gt;{&lt;/span&gt;
        &lt;span style="color: #4c83ff;"&gt;public&lt;/span&gt; &lt;span style="color: #afd8af;"&gt;string&lt;/span&gt; &lt;span style="color: #ff69b4;"&gt;Name&lt;/span&gt; &lt;span style="color: #006400;"&gt;{&lt;/span&gt; &lt;span style="color: #4c83ff;"&gt;get&lt;/span&gt;; &lt;span style="color: #006400;"&gt;}&lt;/span&gt;
    
        &lt;span style="color: #4c83ff;"&gt;public&lt;/span&gt; &lt;span style="color: #afd8af;"&gt;void&lt;/span&gt; &lt;span style="color: #ff1493;"&gt;Greet&lt;/span&gt;&lt;span style="color: #006400;"&gt;()&lt;/span&gt; =&gt; Console.&lt;span style="color: #ff1493;"&gt;WriteLine&lt;/span&gt;&lt;span style="color: #006400;"&gt;(&lt;/span&gt;$&lt;span style="color: #61CE3C;"&gt;"Hello, {Name}"&lt;/span&gt;&lt;span style="color: #006400;"&gt;)&lt;/span&gt;;
    &lt;span style="color: #8b0000;"&gt;}&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    This can be broken up across several source blocks and tangled to a single file:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-org"&gt;First declare a namespace:
    
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+begin_src csharp :tangle SampleClass.cs&lt;/span&gt;
    &lt;span style="color: #4c83ff; background-color: #383838;"&gt;namespace&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #ff69b4; background-color: #383838;"&gt;Chamook&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;.&lt;/span&gt;&lt;span style="color: #ff69b4; background-color: #383838;"&gt;Sample&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;;&lt;/span&gt;
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+end_src&lt;/span&gt;
    
    Then declare the class:
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+begin_src csharp :tangle SampleClass.cs&lt;/span&gt;
    &lt;span style="color: #4c83ff; background-color: #383838;"&gt;public&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;sealed&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;class&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #afd8af; background-color: #383838;"&gt;SampleClass&lt;/span&gt;
    &lt;span style="color: #8b0000; background-color: #383838;"&gt;{&lt;/span&gt;
    &lt;span style="background-color: #383838;"&gt;    &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;public&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #afd8af; background-color: #383838;"&gt;string&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #ff69b4; background-color: #383838;"&gt;Name&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;{&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;get&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;; &lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;}&lt;/span&gt;
    
    &lt;span style="background-color: #383838;"&gt;    &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;public&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #afd8af; background-color: #383838;"&gt;void&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #ff1493; background-color: #383838;"&gt;Greet&lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;()&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; =&gt; Console.&lt;/span&gt;&lt;span style="color: #ff1493; background-color: #383838;"&gt;WriteLine&lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;(&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;$&lt;/span&gt;&lt;span style="color: #61CE3C; background-color: #383838;"&gt;"Hello, {Name}"&lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;)&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;;&lt;/span&gt;
    &lt;span style="color: #8b0000; background-color: #383838;"&gt;}&lt;/span&gt;
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+end_src&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    Will tangle to a single &lt;code&gt;SampleClass.cs&lt;/code&gt; file containing code from all the source blocks that tangle to it in the order that they appear in the
    org file.
    &lt;/p&gt;
    
    &lt;p&gt;
    One org file can also tangle to multiple code files by specifying different filenames in code blocks:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-org"&gt;Namespace for my C# file:
    
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+begin_src csharp :tangle SampleClass.cs&lt;/span&gt;
    &lt;span style="color: #4c83ff; background-color: #383838;"&gt;namespace&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #ff69b4; background-color: #383838;"&gt;Chamook&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;.&lt;/span&gt;&lt;span style="color: #ff69b4; background-color: #383838;"&gt;Sample&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;;&lt;/span&gt;
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+end_src&lt;/span&gt;
    
    Oh that reminds me of a funny javascript story:
    
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+begin_src js :tangle hahaha.js&lt;/span&gt;
    &lt;span style="color: #4c83ff; background-color: #383838;"&gt;function&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #ff1493; background-color: #383838;"&gt;pleaseLaugh&lt;/span&gt;&lt;span style="color: #8b0000; background-color: #383838;"&gt;()&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #8b0000; background-color: #383838;"&gt;{&lt;/span&gt;
    &lt;span style="background-color: #383838;"&gt;  &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;return&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #61CE3C; background-color: #383838;"&gt;"hahaha"&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;;&lt;/span&gt;
    &lt;span style="color: #8b0000; background-color: #383838;"&gt;}&lt;/span&gt;
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+end_src&lt;/span&gt;
    
    Then declare a class in the C# file:
    
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+begin_src csharp :tangle SampleClass.cs&lt;/span&gt;
    &lt;span style="color: #4c83ff; background-color: #383838;"&gt;public&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;sealed&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;class&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #afd8af; background-color: #383838;"&gt;SampleClass&lt;/span&gt;
    &lt;span style="color: #8b0000; background-color: #383838;"&gt;{&lt;/span&gt;
    &lt;span style="background-color: #383838;"&gt;    &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;public&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #afd8af; background-color: #383838;"&gt;string&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #ff69b4; background-color: #383838;"&gt;Name&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;{&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;get&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;; &lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;}&lt;/span&gt;
    
    &lt;span style="background-color: #383838;"&gt;    &lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;public&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #afd8af; background-color: #383838;"&gt;void&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #ff1493; background-color: #383838;"&gt;Greet&lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;()&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; =&gt; Console.&lt;/span&gt;&lt;span style="color: #ff1493; background-color: #383838;"&gt;WriteLine&lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;(&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;$&lt;/span&gt;&lt;span style="color: #61CE3C; background-color: #383838;"&gt;"Hello, {Name}"&lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;)&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;;&lt;/span&gt;
    &lt;span style="color: #8b0000; background-color: #383838;"&gt;}&lt;/span&gt;
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+end_src&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    Will output both the &lt;code&gt;.cs&lt;/code&gt; and the &lt;code&gt;.js&lt;/code&gt; files specified.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org2b58f0e" class="outline-2"&gt;
    &lt;h2 id="org2b58f0e"&gt;Conditional Tangling&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-org2b58f0e"&gt;
    &lt;p&gt;
    For the templates I was creating from an org file, I wanted to be able to pick and choose which parts were included rather than just
    outputting everything. Conveniently emacs can evaluate an emacs-lisp expression as part of the &lt;code&gt;:tangle&lt;/code&gt; definition on a code block,
    meaning that I could check a condition and either return a filename or &lt;code&gt;"no"&lt;/code&gt; which disables tangling for that block. The check
    could look at variables set within the org file, but as I was working on a template that other people might want to use I made it check
    if some dotfiles existed in the same directory:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-org"&gt;#+begin_src bicep :tangle (if (file-exists-p ".Config1") "infra/main.bicep" "no")
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    This block will only be tangled with the &lt;code&gt;main.bicep&lt;/code&gt; file if there is a file called &lt;code&gt;.Config1&lt;/code&gt; in the same directory as the org file.
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgfce8a14" class="outline-2"&gt;
    &lt;h2 id="orgfce8a14"&gt;Backfilling Values with Noweb&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-orgfce8a14"&gt;
    &lt;p&gt;
    Building templates that were configurable in this way led to a scenario where sometimes I would need to include values in an earlier part of a
    bicep file only if a later block was tangled. Source blocks in org mode support using &lt;a href="https://en.wikipedia.org/wiki/Noweb"&gt;noweb&lt;/a&gt; style markup to include either the contents
    or the result of evaluating other blocks in the document, which provides a nice way of solving this problem.
    &lt;/p&gt;
    
    &lt;p&gt;
    In the initial block that may need a value from later, I can enable noweb replacements by specifying &lt;code&gt;:noweb yes&lt;/code&gt; and then add a
    reference to the later contents:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-org"&gt;&lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+begin_src :noweb yes&lt;/span&gt;
    &lt;span style="text-decoration: underline;"&gt;&lt;&lt;maybe-from-later()&gt;&gt;&lt;/span&gt;
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+end_src&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    Then later include a named block, that performs the check for the dotfile and returns a value if it is present, or an empty string otherwise:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-org"&gt;#name: maybe-from-later
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+begin_src emacs-lisp :cache no&lt;/span&gt;
    &lt;span style="color: #8b0000; background-color: #383838;"&gt;(&lt;/span&gt;&lt;span style="color: #4c83ff; background-color: #383838;"&gt;if&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;(&lt;/span&gt;&lt;span style="background-color: #383838;"&gt;file-exists-p &lt;/span&gt;&lt;span style="color: #61CE3C; background-color: #383838;"&gt;".config2"&lt;/span&gt;&lt;span style="color: #006400; background-color: #383838;"&gt;)&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #61CE3C; background-color: #383838;"&gt;"// the file exists"&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #61CE3C; background-color: #383838;"&gt;""&lt;/span&gt;&lt;span style="color: #8b0000; background-color: #383838;"&gt;)&lt;/span&gt;
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+end_src&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-orgac6dd24" class="outline-2"&gt;
    &lt;h2 id="orgac6dd24"&gt;Tangling for the non-Emacs user&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-orgac6dd24"&gt;
    &lt;p&gt;
    A template is less useful if it constrains people to use a specific editor (with a relatively steep learning curve) to be able to get any value from
    it, but fortunately Emacs can be called from the command line to tangle a file so I included a shell script with my template. (I actually tangled
    the shell script from the template itself 🤘):
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-org"&gt;&lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+begin_src bash :tangle tangle.sh :shebang "#!/bin/bash"&lt;/span&gt;
    &lt;span style="background-color: #383838;"&gt;emacs --batch &lt;/span&gt;&lt;span style="color: #61CE3C; background-color: #383838;"&gt;\&lt;/span&gt;
    &lt;span style="background-color: #383838;"&gt;      --eval &lt;/span&gt;&lt;span style="color: #61CE3C; background-color: #383838;"&gt;"(require 'org)"&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #61CE3C; background-color: #383838;"&gt;\&lt;/span&gt;
    &lt;span style="background-color: #383838;"&gt;      --eval &lt;/span&gt;&lt;span style="color: #61CE3C; background-color: #383838;"&gt;"(setq org-confirm-babel-evaluate nil)"&lt;/span&gt;&lt;span style="background-color: #383838;"&gt; &lt;/span&gt;&lt;span style="color: #61CE3C; background-color: #383838;"&gt;\&lt;/span&gt;
    &lt;span style="background-color: #383838;"&gt;      --eval &lt;/span&gt;&lt;span style="color: #61CE3C; background-color: #383838;"&gt;'(org-babel-tangle-file "file.org")'&lt;/span&gt;
    &lt;span style="color: #008ED1; background-color: #2b2b2b;"&gt;#+end_src&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    This passes several snippets of emacs-lisp for emacs to evaluate:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-emacs-lisp"&gt;&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;&lt;span style="color: #4c83ff;"&gt;require&lt;/span&gt; '&lt;span style="color: #96CBFE;"&gt;org&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    First ensures that org-mode is loaded, then we edit the org-babel configuration slightly:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-emacs-lisp"&gt;&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;&lt;span style="color: #4c83ff;"&gt;setq&lt;/span&gt; org-confirm-babel-evaluate nil&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    This disables the prompt before evaluating each code block so that a user doesn't have to type &lt;code&gt;yes&lt;/code&gt; for each block that is evaluated.
    With that config change in place it's just a matter to call the function that will actually tangle our org file and tell it which file to operate on:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-emacs-lisp"&gt;&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;org-babel-tangle-file &lt;span style="color: #61CE3C;"&gt;"file.org"&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    With this the org file is tangled and nobody had to open an emacs window or learn any keybindings 😅 
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
    &lt;div id="outline-container-org7a1bd1a" class="outline-2"&gt;
    &lt;h2 id="org7a1bd1a"&gt;Exporting&lt;/h2&gt;
    &lt;div class="outline-text-2" id="text-org7a1bd1a"&gt;
    &lt;p&gt;
    After working with org files a bunch to create this template, I discovered that there is also a fairly customizable export functionality -
    by setting a few config values:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-emacs-lisp"&gt;&lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;&lt;span style="color: #4c83ff;"&gt;setq&lt;/span&gt; org-html-doctype &lt;span style="color: #61CE3C;"&gt;"html5"&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;
    &lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;&lt;span style="color: #4c83ff;"&gt;setq&lt;/span&gt; org-html-postamble-format '&lt;span style="color: #006400;"&gt;(&lt;/span&gt;&lt;span style="color: #ff1493;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;"en"&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"&lt;footer class=\"page-footer\"&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;&lt;div class=\"container\"&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;  &lt;a href=\"../index.html\"&gt;&amp;lt;- M-x find-more-content&lt;/a&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;&lt;/div&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;&lt;/footer&gt;"&lt;/span&gt;&lt;span style="color: #ff1493;"&gt;)&lt;/span&gt;&lt;span style="color: #006400;"&gt;)&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;
    &lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;&lt;span style="color: #4c83ff;"&gt;setq&lt;/span&gt; org-html-postamble 't&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;
    &lt;span style="color: #8b0000;"&gt;(&lt;/span&gt;&lt;span style="color: #4c83ff;"&gt;setq&lt;/span&gt; org-html-preamble-format '&lt;span style="color: #006400;"&gt;(&lt;/span&gt;&lt;span style="color: #ff1493;"&gt;(&lt;/span&gt;&lt;span style="color: #61CE3C;"&gt;"en"&lt;/span&gt; &lt;span style="color: #61CE3C;"&gt;"&lt;header&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;&lt;div class=\"container\"&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;  &lt;h1 class=\"glitch-text\" data-text=\"%t\"&gt;%t&lt;/h1&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;  &lt;span class=\"subtitle\"&gt;%s&lt;/span&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;&lt;/div&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;&lt;div class=\"byline\"&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;  &lt;div class=\"container\"&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;    &lt;p&gt;By &lt;a href=\"https://twitter.com/chamooktweets\"&gt;Adam Guest&lt;/a&gt; - %d&lt;/p&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;  &lt;/div&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;&lt;/div&gt;&lt;/span&gt;
    &lt;span style="color: #61CE3C;"&gt;&lt;/header&gt;"&lt;/span&gt;&lt;span style="color: #ff1493;"&gt;)&lt;/span&gt;&lt;span style="color: #006400;"&gt;)&lt;/span&gt;&lt;span style="color: #8b0000;"&gt;)&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    And adding some extra values to include in the html at the top of the document:
    &lt;/p&gt;
    
    &lt;div class="org-src-container"&gt;
    &lt;pre class="src src-org"&gt;&lt;span style="color: #8B8989; font-style: italic;"&gt;#+options: toc:nil num:nil html-style:nil html5-fancy:'t title:nil exports:both&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_content_class: container&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head: &lt;link rel="stylesheet" href="../style.css"&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head: &lt;meta charset="utf-8"&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head:&lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head:&lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head:&lt;link rel="apple-touch-icon" sizes="180x180" href="../apple-touch-icon.png"&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head:&lt;link rel="icon" type="image/png" sizes="32x32" href="../favicon-32x32.png"&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head:&lt;link rel="icon" type="image/png" sizes="16x16" href="../favicon-16x16.png"&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head:&lt;meta property="og:url" content="&lt;a href="https://chamook.lol/literate-programming-with-org/"&gt;https://chamook.lol/literate-programming-with-org/&lt;/a&gt;" /&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head:&lt;meta property="og:image" content="&lt;a href="https://chamook.lol/literate-programming-with-org/card.png"&gt;https://chamook.lol/literate-programming-with-org/card.png&lt;/a&gt;" /&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head:&lt;meta property="og:type" content="article" /&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head:&lt;meta property="article:published_time" content="2022-08-12T00:00:00+00:00" /&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head:&lt;meta name="twitter:card" content="summary_large_image" /&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head:&lt;meta property="twitter:image" content="&lt;a href="https://chamook.lol/literate-programming-with-org/card.png"&gt;https://chamook.lol/literate-programming-with-org/card.png&lt;/a&gt;" /&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head:&lt;meta property="twitter:title" content="Literate Programming with Org Mode &#129412;" /&gt;&lt;/span&gt;
    &lt;span style="color: #8B8989; font-style: italic;"&gt;#+html_head:&lt;meta property="twitter:description" content="Broke: Generate docs from code | Woke: Generate code from docs &#128526;" /&gt;&lt;/span&gt;
    &lt;/pre&gt;
    &lt;/div&gt;
    
    &lt;p&gt;
    I can use &lt;code&gt;org-export-dispatch&lt;/code&gt; to generate this html page 😍 
    &lt;/p&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    &lt;/div&gt;
    
  </description>
  <pubDate>Fri, 12 Aug 2022 00:00:01 +0100</pubDate>
  <guid>https://chamook.lol/literate-programming-with-org/</guid>
  </item>

</channel>
</rss>
