text:
---
manufacturer: Xiaomi/MiaoMiaoCe
name: "Alarm clock"
model: MHO-C401
image: "MHO-C401.jpg"
physical_description: "Small square body, E-Ink display"
broadcasted_properties:
  - temperature
  - humidity
  - battery
  - voltage
  - rssi
broadcasted_property_notes:
  - property: voltage
    note: battery voltage is only available with custom firmware
  - property: rssi
    note: >
      The RSSI sensor is disabled by default. You can enable the RSSI sensor by going to `configuration`, `integrations`, select `devices` on the BLE monitor integration tile and select your device. Click on the `+1 disabled entity` to show the disabled sensor and select the disabled entity. Finally, click on `Enable entity` to enable it.
broadcast_rate: "1/10min. (battery level 1/hr.)"
active_scan:
encryption_key: true
custom_firmware:
  - name: pvvx
    url: https://github.com/pvvx/ATC_MiThermometer
notes:
  - Custom firmware's broadcast temperature, humidity, battery voltage and battery level in percent. Broadcast interval can be set by the user and encryption can be used as an option. BLE monitor will automatically use the advertisement type with the highest accuracy, when setting the firmware to broadcast all advertisement types.
---


text:
---
layout: page
permalink: "/events/"
title: "OSIPI events"
header: no
#subheadline: "... because we need one!"
---

## Upcoming Events

### ISMRM Member-Initiated Symposium “Open Source Initiative for Perfusion Imaging”

**When**: Monday, May 13th from 1:45-3:45 pm.

**Where**: ISMRM 27th Annual meeting and exhibition, Room 513A-C [Montreal Convention Center, Montreal, QC, Canada](https://goo.gl/maps/pKi3mntz5nP2)

**Registration**: You need to be a registered attendee of ISMRM to participate

**Agenda**: You can find the details of this event at [the ISMRM page of the event](https://www.ismrm.org/19/program_files/MIS04.htm).

### OSIPI 1st Annual Face-to-Face Meeting

**When**: Friday, May 17th from 10:30 am to 12:45 pm

**Where**: [McGill University Health Centre (Room RBC Conference Room, DS1.1427), 1001 Boulevard Décarie, Montreal, QC, Canada](https://goo.gl/maps/KfZJWAmeFhK2)

**Registration**: This meeting is free, but registration is required (and most details) are available [via EventBrite](https://www.eventbrite.com/e/osipis-first-annual-face-to-face-meeting-in-montreal-2019-tickets-57199759019)

**Agenda**: The agenda of this meeting is being finalized, but the program will include the following items:
* Introduction of the OSIPI EMB members
* Presentation of OSIPI aims and task force concept in direct interaction with the audience
* Presentation of the survey results
* Open source software demonstrations
* Task force definitions and roles in interaction with the audience
* Open discussions with the attendees

license: MIT

branch_name: refs/heads/master

extension: md

license_type: permissive


text:
[![CI Status](https://github.com/AY2021S1-CS2103T-T11-1/tp/workflows/Java%20CI/badge.svg)](https://github.com/AY2021S1-CS2103T-T11-1/tp/actions)

# StonksBook

![Ui](docs/images/Ui.png)

StonksBook is a desktop app for managing contacts, optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). This brownfield project is adapted and evolved from the CS2103T sample project **AddressBook Level 3**.

For a detailed documentation of StonksBook, visit **[our product website](https://ay2021s1-cs2103t-t11-1.github.io/tp/)**.

## Acknowledgements
* This project is based on the AddressBook-Level3 project created by the [SE-EDU Initiative](https://se-education.org).

gha_language: Java

gha_license_id: NOASSERTION


text:
---
id: build-tools.prebuild
title: prebuild
prev: build-tools.node-pre-gyp
---

## Introduction

One of the limitations of implementing native add-on modules is that at some point they need to be compiled and linked. In the absence of a downloadable binary, each user of a native add-on will need to compile and link the module. This requires each user to have the necessary C/C++ build tools installed.

An alternative is for the native add-on maintainer to pre-build binaries for supported platforms and architectures and to upload these binaries to a location where users can download them.

This is the specific solution offered by [prebuild](https://github.com/prebuild/prebuild#prebuild).

> Note that Node-API support was added to prebuild in version 8.1.0.

> [node-pre-gyp](node-pre-gyp) is an alternative tool that addresses this same issue.

This page describes the modifications required to an Node-API add-on module in order for it to support prebuild.

## prebuild and prebuild-install

The capabilities offered by prebuild are actually delivered by two separate packages:

- [prebuild](https://github.com/prebuild/prebuild) — For native add-on developers.
- [prebuild-install](https://github.com/prebuild/prebuild-install) — For the users of your native add-on.

As a developer, you will use `prebuild` to build and upload your binaries. The users of your native add-on will use `prebuild-install` to first attempt to download one of your pre-built binaries before falling back to building the binary themselves.

## Installing

When getting started with prebuild, it's easiest to install `prebuild` as a global package:

```bash
npm install -g prebuild
```

> As you become proficient in prebuild, you may choose to alternatively install `prebuild` as one of your `devDependencies`.

## GitHub Releases

By default, prebuild uploads generated binaries as [GitHub Releases](https://help.github.com/en/github/administering-a-repository/about-releases). Creating and uploading GitHub releases requires the use of a GitHub personal access token. The steps to create a token are as follows:

- Go to the Github page to create [personal access tokens](https://github.com/settings/tokens). (You may need to log in.)

- Click `Generate new token`.

- Under `Select scopes`, your token must have either `public_repo` or `repo` scope to upload releases.

  - Choose `public_repo` if you will be uploading only to public repositories.

  - Choose `repo` if you will be uploading to private repositories.

- Click `Generate token`.

- Make a note of the generated token as this will be the only time it is visible.

- Create the `GITHUB_TOKEN` environment variable containing the token.  For example:

  ```
  export GITHUB_TOKEN=<github-token>
  ```

  Replace the text `<github-token>` with the token generated above.

## package.json

### The `repository` property

Since prebuild uploads your binary to GitHub, you must specify the GitHub repository in a `repository` property:

```json
  "repository": {
    "type": "git",
    "url": "https://github.com/itsmecooldude/my-napi-addon.git"
  }
```

### The `dependencies` property

The users of your native add-on will need to install `prebuild-install` in order to download your pre-built binary. This makes `prebuild-install` a dependency:

```json
  "dependencies": {
    "prebuild-install": "^5.3.3"
  }
```

### The `scripts` properties

Here are some suggested `scripts` entries to get started:

```json
  "scripts": {
    "install": "prebuild-install --runtime napi || node-gyp rebuild",
    "rebuild": "node-gyp rebuild",
    "prebuild": "prebuild --runtime napi --all --strip --verbose",
    "upload": "prebuild --runtime napi --upload ${GITHUB_TOKEN}"
  }
```

For the `prebuild` and `prebuild-install` commands, the `--runtime` argument must be `napi` to request Node-API builds. When requesting Node-API builds, the module's `package.json` file _must_ include a `binary` property as described next. And the `binding.gyp`  `CMakeLists.txt` file _must_ include a define for `NAPI_VERSION` as described below.

One or more `--target` arguments may be specified to request builds for specific Node-API versions. Node-API versions are positive integer values. Alternatively, `--all` may be used to request builds for all Node-API versions supported by the module.

In the absence of both `--target` and `--all` arguments, `prebuild` will build the most current version of the module supported by the Node instance performing the build.

### The `binary` property

Native modules that are designed to work with [Node-API](https://nodejs.org/api/n-api.html) must explicitly declare the Node-API version(s) against which they can build. This is accomplished by including a `binary` property on the module's `package.json` file. For example:

```json
"binary": {
  "napi_versions": [2,3]
}
```

In the absence of a need to compile against a specific Node-API version, the value `3` is a good choice as this is the Node-API version that was supported when Node-API left experimental status.

Modules that are built against a specific Node-API version will continue to operate indefinitely, even as later versions of Node-API are introduced.

## NAPI_VERSION

The Node-API header files supplied with Node use the `NAPI_VERSION` preprocessor value supplied by the user to configure each build to the specific Node-API version for which the native addon is being built. In addition, the module's C/C++ code can use this value to conditionally compile code based on the Node-API version it is being compiled against.

`prebuild` supports two build backends: [`node-gyp`](https://github.com/nodejs/node-gyp) and [`cmake-js`](https://github.com/cmake-js/cmake-js). The `NAPI_VERSION` value is configured differently for each backend.

### node-gyp

The following code must be included in the `binding.gyp` file of modules targeting Node-API:

```json
"defines": [
  "NAPI_VERSION=<(napi_build_version)"
]
```

### cmake-js

The following line must be included in the `CMakeLists.txt` file of modules targeting Node-API:

```cmake
add_compile_definitions(NAPI_VERSION=${napi_build_version})
```

## Building and uploading your binary

Using the `package.json` `scripts` entries as a starting point, this command will build and package your native add-on:

```
npm run prebuild
```

You can run this command as often as necessary.

When you're ready, run this command to upload your compiled binary to GitHub:

```
npm run upload
```

> This command requires that the `GITHUB_TOKEN` environment variable contains a valid GitHub token as described above.

Once you become proficient in prebuild, you can modify the `package.json` `scripts` entries to meet your specific needs.

## Life for your users

You've declared `prebuild-install` as a dependency. The `install` script in your `package.json` file looks like this:

```json
    "install": "prebuild-install --runtime napi || node-gyp rebuild"
```

When a user installs your native add-on, the `prebuild-install` tool first looks to see if it can locate a suitable pre-built binary on GitHub for the user's specific Node-API version, architecture, and platform. If the binary is found, `prebuild-install` downloads, unpacks, and installs the binaries in the correct location.

If the binary is not found, the `install` script falls back to whatever is specified after the `||`. In this case, a `node-gyp rebuild` is triggered which will attempt to build the binary on the user's machine.

## Resources

[prebuild](https://github.com/prebuild/prebuild) Project GitHub page

[prebuild-install](https://github.com/prebuild/prebuild-install) Project GitHub page

repository: nodejs/node-addon-examples

branch_name: refs/heads/main

repo_name: nodejs/node-addon-examples


text:
# CHANGELOG for 1.1 (and 2.0)

This document describes all the significant changes made between 1.0 and 1.1 branches.
It also covers transition to 2.0 branch, since 1.1 and 2.0 are backwards compatibile.

## Admin elements' changes

### Architectural changes

#### Splitting monolithic CRUD

The major change in admin-bundle's architecture is splitting one monolithic
[``FSi\Bundle\AdminBundle\Admin\CRUD\CRUDInterface``](Admin/CRUD/CRUDInterface.php) into a couple of smaller, more
specialized interfaces of admin elements:

- [``FSi\Bundle\AdminBundle\Admin\CRUD\ListElement``](Admin/CRUD/ListElement.php) - creates list of items using
  [fsi/datasource](https://github.com/fsi-open/datasource) and [fsi/datagrid](https://github.com/fsi-open/datagrid)
- [``FSi\Bundle\AdminBundle\Admin\CRUD\FormElement``](Admin/CRUD/FormElement.php) - creates form for a single item
- [``FSi\Bundle\AdminBundle\Admin\CRUD\BatchElement``](Admin/CRUD/BatchElement.php) - performs some simple action on
  a single item

These interfaces have been combined again into
[``FSi\Bundle\AdminBundle\Admin\CRUD\CRUDElement``](Admin/CRUD/CRUDElement.php) which behaves exactly as the old one
[``FSi\Bundle\AdminBundle\Admin\CRUD\CRUDInterface``](Admin/CRUD/CRUDInterface.php) to ease the upgrade process.

#### New batch element

This [element](Admin/CRUD/BatchElement.php) was created to allow performing of repeatable operations on items selected
by user on the list. Please refer to the [full description](Resources/doc/admin_element_batch.md) of how to use such an
admin element. The first general use case of such an operation is deleting selected items, which is implemented as a
batch admin element. Other examples are activating/deactivating selected users, turning on/off visibility of selected
articles, moving selected articles to the archive, etc. New batch elements can be simply linked to the list element
using batch column options in datagrid.

#### New display element

Brand new [``FSi\Bundle\AdminBundle\Admin\Display\Element``](Admin/Display/Element.php) has been introduced and it
creates a specialized display object for a single item. This object is used to show selected properties of an item
(entity) in a standardized way.

#### Consequences

Thanks to the introducing of smaller admin elements it's now possible to build more complicated administration
interfaces with several different forms and/or displays for one type of item/entity. These different forms and/or
displays can be i.e. separately secured for different user roles.

Creation and editing of an item was previously handled by two different actions and their templates, but since one
admin list element can be linked to more than one form, such a separation is no longer necessary. The "add" button
can simply link to different form element than "edit" button.

### Functional changes

#### Admin element registration

There is a new and easier way of registering admin elements by marking them with ``@Admin\Element`` annotation. If
you wish to set custom options for admin element using this method you have to do this in ``setDefaultOptions()``
through ``$resolver->setDefaults()``.

#### No confirmation during delete

Deleting of selected items no longer display intermediate action with confirmation form. Such a confirmation can
be added by attaching some JS to the "Ok" button which performs selected batch action.

#### Admin menu building

Method ``getName()`` was removed from all admin elements. Previously it was used only during building of the admin menu.
Now admin menu is built using additional configuration file as described [here](Resources/docs/menu.md).

### Options changes

#### Removed options

The following options were removed from [``FSi\Bundle\AdminBundle\Admin\CRUD\AbstractCRUD``](Admin/CRUD/AbstractCRUD)

- ``menu`` - removed from all admin elements in favour of new method of menu building method
- ``allow_edit`` - removed because there is no longer any specific "edit" action
- ``crud_list_title`` - removed in favour of ``header`` block in [list template](Resources/views/List/list.html.twig)
- ``crud_create_title`` - removed in favour of ``header`` block in [form template](Resources/views/Form/form.html.twig)
- ``crud_edit_title`` - removed in favour of ``header`` block in [form template](Resources/views/Form/form.html.twig)
- ``template_crud_delete`` - removed because delete action has no longer any intermediate confirmation action

#### Added options

- ``template_list`` - template for the list action, its default value is taken from deprecated ``template_crud_list``
  option
- ``template_form`` - template for the form action, its default value is taken from deprecated ``template_crud_edit``
  option

#### Deprecated options

- ``template_crud_list`` - will be removed in favor of ``template_list``
- ``template_crud_edit`` - will be removed in favor of ``template_form``
- ``template_crud_create`` - will be removed in favor of ``template_form``

**Important!** - if you are using both ``template_crud_create`` and ``template_crud_edit``, please note that they have
to have the same value since there are no longer different contexts handling creation and update of an item.

### Templates changes

#### Removed templates

- ``Resources/views/CRUD/List/*.html.twig`` - these were the rarely used partials included by
  ``Resources/views/CRUD/list.html.twig``. Since there are gone, overwriting them in ``app/Resources`` has no longer
  any effect and ``Resources/views/CRUD/list.html.twig`` should be overwritten instead.
- ``Resources/views/CRUD/delete.html.twig`` - it is no longer needed since there is no longer any confirmation step
  while deleting selected items.

#### Changed templates

- ``Resources/views/CRUD/list.html.twig`` - it extends ``Resources/views/List/list.html.twig``. Since batch actions are
  added thought datagrid batch column's options, there are no longer ``batch_action`` and ``batch_form`` blocks to
  overwrite. There is a new block ``batch_actions`` containing the whole batch action selection form.
- ``Resources/views/CRUD/edit.html.twig`` - was removed in favour of ``Resources/views/CRUD/form.html.twig`` and
  overwriting it in ``app/Resources`` has no longer any effect.
- ``Resources/views/CRUD/create.html.twig`` - was removed in favour of ``Resources/views/CRUD/form.html.twig`` and
  overwriting it in ``app/Resources`` has no longer any effect.
- ``Resources/views/Form/form_div_layout.html.twig`` - was renamed to ``Resources/views/Form/form_theme.html.twig``.

## Contexts' changes

### Contexts handlers are more generic

All contexts and handlers classes which previously existed in ``FSi\Bundle\AdminBundle\Doctrine\Context`` namespace have
been removed in favour of new generic (non doctrine-dependent) contexts and handlers in
``FSi\Bundle\AdminBundle\Admin\CRUD\Context`` namespace.

### Event names changes

Since contexts are rebuild from scratch the naming of events has been also changed.

    1.0.*
    ~1.1

    constant
    name
    constant
    name

    CRUDEvents::CRUD_LIST_CONTEXT_POST_CREATE	'admin.crud.list.context.post_create'
    -	-

    CRUDEvents::CRUD_LIST_DATASOURCE_REQUEST_PRE_BIND	'admin.crud.list.datasource.request.pre_bind'
    ListEvents::LIST_DATASOURCE_REQUEST_PRE_BIND	'admin.list.datasource.request.pre_bind'

    CRUDEvents::CRUD_LIST_DATASOURCE_REQUEST_POST_BIND	'admin.crud.list.datasource.request.post_bind'
    ListEvents::LIST_DATASOURCE_REQUEST_POST_BIND	'admin.list.datasource.request.post_bind'

    CRUDEvents::CRUD_LIST_DATAGRID_DATA_PRE_BIND	'admin.crud.list.datagrid.data.pre_bind'
    ListEvents::LIST_DATAGRID_DATA_PRE_BIND	'admin.list.datagrid.data.pre_bind'

    CRUDEvents::CRUD_LIST_DATAGRID_DATA_POST_BIND	'admin.crud.list.datagrid.data.post_bind'
    ListEvents::LIST_DATAGRID_DATA_POST_BIND	'admin.list.datagrid.data.post_bind'

    CRUDEvents::CRUD_LIST_DATAGRID_REQUEST_PRE_BIND	'admin.crud.list.datagrid.request.pre_bind'
    ListEvents::LIST_DATAGRID_REQUEST_PRE_BIND	'admin.list.datagrid.request.pre_bind'

    CRUDEvents::CRUD_LIST_DATAGRID_REQUEST_POST_BIND	'admin.crud.list.datagrid.request.post_bind'
    ListEvents::LIST_DATAGRID_REQUEST_POST_BIND	'admin.list.datagrid.request.post_bind'

    CRUDEvents::CRUD_LIST_RESPONSE_PRE_RENDER	'admin.crud.list.response.pre_render'
    ListEvents::LIST_RESPONSE_PRE_RENDER	'admin.list.response.pre_render'

    CRUDEvents::CRUD_CREATE_CONTEXT_POST_CREATE
CRUDEvents::CRUD_EDIT_CONTEXT_POST_CREATE
    'admin.crud.create.context.post_create'
'admin.crud.edit.context.post_create'
    -	-

    CRUDEvents::CRUD_CREATE_FORM_REQUEST_PRE_SUBMIT
CRUDEvents::CRUD_EDIT_FORM_REQUEST_PRE_SUBMIT
    admin.crud.create.form.request.pre_submit'
'admin.crud.edit.form.request.pre_submit'
    FormEvents::FORM_REQUEST_PRE_SUBMIT	'admin.form.request.pre_submit'

    CRUDEvents::CRUD_CREATE_FORM_REQUEST_POST_SUBMIT
CRUDEvents::CRUD_EDIT_FORM_REQUEST_POST_SUBMIT
    'admin.crud.create.form.request.post_submit'
'admin.crud.edit.form.request.post_submit'
    FormEvents::FORM_REQUEST_POST_SUBMIT	'admin.form.request.post_submit'

    CRUDEvents::CRUD_CREATE_ENTITY_PRE_SAVE
CRUDEvents::CRUD_EDIT_ENTITY_PRE_SAVE
    'admin.crud.create.entity.pre_save'
'admin.crud.edit.entity.pre_save'
    FormEvents::FORM_DATA_PRE_SAVE	'admin.form.data.pre_save'

    CRUDEvents::CRUD_CREATE_ENTITY_POST_SAVE
CRUDEvents::CRUD_EDIT_ENTITY_POST_SAVE
    'admin.crud.create.entity.post_save'
'admin.crud.edit.entity.post_save'
    FormEvents::FORM_DATA_POST_SAVE	'admin.form.data.post_save'

    CRUDEvents::CRUD_CREATE_RESPONSE_PRE_RENDER
CRUDEvents::CRUD_EDIT_RESPONSE_PRE_RENDER
    'admin.crud.create.response.pre_render'
'admin.crud.edit.response.pre_render'
    FormEvents::FORM_RESPONSE_PRE_RENDER	'admin.form.response.pre_render'

    CRUDEvents::CRUD_DELETE_CONTEXT_POST_CREATE	'admin.crud.delete.context.post_create'
    -	-

    CRUDEvents::CRUD_DELETE_FORM_PRE_SUBMIT	'admin.crud.delete.form.pre_submit'
    BatchEvents::BATCH_REQUEST_PRE_SUBMIT	'admin.batch.request.pre_submit'

    CRUDEvents::CRUD_DELETE_FORM_POST_SUBMIT	'admin.crud.delete.form.post_submit'
    BatchEvents::BATCH_REQUEST_POST_SUBMIT	'admin.batch.request.post_submit'

    CRUDEvents::CRUD_DELETE_ENTITIES_PRE_DELETE	'admin.crud.delete.entities.pre_delete'
    BatchEvents::BATCH_OBJECTS_PRE_APPLY	'admin.batch.objects.pre_apply'

    CRUDEvents::CRUD_DELETE_ENTITIES_POST_DELETE	'admin.crud.delete.entities.post_delete'
    BatchEvents::BATCH_OBJECTS_POST_APPLY	'admin.batch.objects.post_apply'

Additional notes:

- since there are no different events when creating and editing of an item you should distinguish these two situations
  by examining ``$event->getForm()->getData()`` in your event handler.
- since all batch events are common for all batch actions (i.e. not only delete), you should identify the action being
  performed by examining the class of ``$event->getElement()`` in your event handler.

## Bundle configuration changes

### Configuring admin menu

Admin menu is read from %kernel.project_dir%/config/admin_menu.yml by default but the path to menu file can be changed by
setting ``fsi_admin.menu_config_path`` configuration option.

### Configuring language switch

If you want your admin to be multilingual you must set the array of supported locales in ``fsi_admin.locales``
configuration option.

### Removed configuration options

The following bundle configuration options have been removed due to removal of their underlying functionality:

- ``fsi_admin.display_language_switch``
- ``fsi_admin.templates.crud_create``
- ``fsi_admin.templates.crud_edit`` was renamed to ``fsi_admin.templates.crud_form``
- ``fsi_admin.templates.crud_delete``
- ``fsi_admin.templates.edit_form_theme``
- ``fsi_admin.templates.create_form_theme``
- ``fsi_admin.templates.delete_form_theme``
- ``fsi_admin.templates.resource_form_theme``

### Routing changes

The following old routes have been marked deprecated and redirected to the new routes

- ``fsi_admin_crud_list`` -> ``fsi_admin_list``
- ``fsi_admin_crud_create`` -> ``fsi_admin_form``
- ``fsi_admin_crud_edit`` -> ``fsi_admin_form``
- ``fsi_admin_crud_delete`` -> ``fsi_admin_batch``

## Removed classes and interfaces

    Old interface/class/namespace	New interface/class/namespace

    FSi\Bundle\AdminBundle\Doctrine\Admin\Context
    FSi\Bundle\AdminBundle\Admin\CRUD\Context

    FSi\Bundle\AdminBundle\Admin\Doctrine
    FSi\Bundle\AdminBundle\Doctrine\Admin

    FSi\Bundle\AdminBundle\Admin\Context\ContextManagerInterface
    FSi\Bundle\AdminBundle\Admin\Context\ContextManager

    FSi\Bundle\AdminBundle\Controller\CRUDController

      FSi\Bundle\AdminBundle\Controller\ListController,
      FSi\Bundle\AdminBundle\Controller\FormController,
      FSi\Bundle\AdminBundle\Controller\BatchController

    FSi\Bundle\AdminBundle\Menu\MenuBuilder
    FSi\Bundle\AdminBundle\Menu\Builder

## Deprecated classes and interfaces

    Old interface/class/namespace	New interface/class/namespace

    FSi\Bundle\AdminBundle\Admin\ElementInterface
    FSi\Bundle\AdminBundle\Admin\Element

    FSi\Bundle\AdminBundle\Admin\CRUD\CRUDInterface
    FSi\Bundle\AdminBundle\Admin\CRUD\CRUDElement

      FSi\Bundle\AdminBundle\Admin\CRUD\DataGridAwareInterface,
      FSi\Bundle\AdminBundle\Admin\CRUD\DataSourceAwareInterface

    FSi\Bundle\AdminBundle\Admin\CRUD\ListElement

    FSi\Bundle\AdminBundle\Admin\CRUD\FormAwareInterface
    FSi\Bundle\AdminBundle\Admin\CRUD\FormElement

      FSi\Bundle\AdminBundle\Admin\ResourceRepository\ResourceInterface,
      FSi\Bundle\AdminBundle\Admin\ResourceRepository\AbstractResource

    FSi\Bundle\AdminBundle\Admin\ResourceRepository\Element

    FSi\Bundle\AdminBundle\Doctrine\Admin\CRUDInterface
    FSi\Bundle\AdminBundle\Doctrine\Admin\Element

    FSi\Bundle\AdminBundle\Doctrine\Admin\DoctrineAwareInterface
    FSi\Bundle\AdminBundle\Doctrine\Admin\Element

repository: fsi-open/admin-bundle

gha_language: PHP

gha_license_id: MIT

repo_name: fsi-open/admin-bundle


text:
---
title: Manuscript submission guidelines
layout: page
speaker: false
categories: [page]
date: 2015-04-02
comments: true
---

It seems that the best way to format the extended article according the required [template](http://sci.fo/isisword) of Is4Is summit is the manual copy-pasting of the text paragraph by paragraph. Unfortunately. Below are the steps for the effort involved that are proven to work. Probably there are other methods of aplying the template (e.g. applying it to the existing file), but I would advice not to do that unless you are an expert in MS Word. [Here](http://sciforum.net/conference/isis-summit-vienna-2015/page/instructions) are original instructions from Is4Is (look under *Extended Abstract Format*).

**Step 1:** Download the [template](http://sci.fo/isisword) and open it with MS Word. This will open a new document based on template file (.dot).

**Step 2:** Save the opened file to a "real" document you will want to edit with `File` -> `Save As` -> `Word Document`. This step should produce a file with *.docx or *.doc extension depending on the Word version used.

**Step 3:** Prepare a hyper-speedy copy-pasting workspace:

**Sub-Step 3.1:** Open the newly created file (will call *manuscript* further);

**Sub-Step 3.2:** Open your abstract which is to be formatted (will call *original* further);

**Sub-Step 3.3:** Display both documents side-by-side with `View` -> `View Side by Side` (this is not really necessary, but very convienent for otherwise frustrating jumping from one window to another while copy-pasting). You should have something like that:

{: .center}
![]({{site.baseurl}}/img/misc/side_by_side_view.png){: width="50%"}

**Step 4:** Copy the title, authors, addresses, the text of the abstract and references from the *original* to *manuscript*. There are two options how to do that and I will explain both:

**Option 1: Using style selector:**

* Copy the paragraphs where they belong wihtout thinking too much about the "local" formatting (explained in option 2). Chances are, that some paragraphs will carry their formatting togehter with the 'end of paragraph' symbol. Also, the copied text may not be attached to the appropriate style (defined by the template). Let them.

* Apply the appropriate styles to the appropriate paragraphs with the Word style selector. The styles required by the Is4Is are prefixed with **M_** in the template (i.e. **M_title**, **M_text**, etc.);

* The style selector (at least in Word 2007) is accessible here:

{: .center}
![]({{site.baseurl}}/img/misc/style_selector.png){: width="50%"}

* And looks like this (see **M_everything** styles):

{: .center}
![]({{site.baseurl}}/img/misc/styles_toolbar.png){: width="25%"}

* Having all this, the formatting is assigned by selecting (or just placing the cursor on) the appropriate paragraph and after after that clicking on the needed style in the "Style toolbar"  (see screenshot above).

**Option 2: Trying to avoid style selector (needs some precision):**

* First, enable what is called "show paragraph marks and other hidden formatting symbols". This is done by pressing ¶ symbol somewhere in the `Home` toolbar (as shown below for Word 2010). It is a good idea to do that for both the *manuscript* and the *source*.

{: .center}
![]({{site.baseurl}}/img/misc/formatting_sign.png){: width="50%"}

* Now, just copy paragraphs from the *original* to the *manuscript* to where they belong. The reason of having the  ¶ symbol is in order **not to copy it**. The World is keeping all the formatting of the text in the paragraph symbol (see [here](http://word.tips.net/T000168_Understanding_How_Word_Stores_Paragraph_Formatting.html) for more). Therefore, if you are not using World styles from the beginning (and I have learned that quite some people do not), it makes sense of being wary of the ¶ symbol in order not to copy the local formatting which messes things up considerably...

* My own way is to use **Option 2** initially but then still check the styles using **Option 1**....

Hope this helps. Please use comments in case I made something more complicated than it really is...

branch_name: HEAD

extension: markdown


text:
# TODO List App

## By Bobby Martin and Luke Stockburger

# Description
This is a TODO List application using Objects and jQuery

# Specifications
* The program adds a task
  * **Input Example: Get Bananas**
  * **Output Example: "Get Bananas"**

# Setup Requirements
* Clone this repository
* Open in web browser or text editor

# Technologies
* HTML
* CSS
* JavaScript

This project uses the _MIT License_
© **Bobby Martin** 2018


text:
---
layout: post
title: Installing and Using Apigility on IBM i
excerpt: Using Apigility on the IBM i to access DB2 data.
categories:
    - ibm i
    - apigility
    - db2
---

* TOC
{:toc}

### Install Apigility

I find the easiest way to accomplish this on the IBM i is to use php itself on command line:

{% highlight bash %}
$ php -r "readfile('https://apigility.org/install');" | php
{% endhighlight %}

After this is ran, Apigility will try to serve itself up. While it is successful in doing so, I have not been able
to visit Apigility without errors when it is running this way on the IBM i. Therefore, I set it up normally through
apache:

{% highlight apache %}
<VirtualHost *:80>
    ServerName api.ibmiserver.com
    DocumentRoot /path/to/apigility/public

    <Directory "/path/to/apigility/public">
        Options FollowSymLinks
        order allow,deny
        allow from all
        AllowOverride all
    </Directory>

    AllowEncodedSlashes On
</VirtualHost>
{% endhighlight %}

That should do it! Apigility should be running fine at the address provided as ServerName.

### Create a DB2 database adapter

Click on `Database` in the upper navigation, then click `New DB Adapter` in the content area.
Fill out the necessary fields and click `Save`.

![New Database Adapter Screenshot]({{site.url}}/images/new-database-adapter.png)

The adapter options can be added and edited through the interface as well:

![Edit Database Driver Options Screenshot]({{site.url}}/images/edit-database-driver-options.png)

If left with no options set, then we are limited to using the `dot` syntax, (`library.file`) only. All column names
will be uppercase as well. Some helpful options to set in `local.php`:

{% highlight php %}
<?php
// config/autoload/local.php
return [
    'db' => [
        'adapters' => [
            'ibmdb' => [
                'database' => 'SXXXXXXX',
                'driver' => 'IbmDb2',
                'username' => 'user',
                'password' => 'password',
                'driver_options' => [
                    'i5_naming' => 1, // This allows us to write with slashes as well. LIBRARY/FILE
                    'db2_attr_case' => 1, // This forces all returned column names to lowercase. Personal preference.
                    // Other helpful options can be found at: http://php.net/manual/en/function.db2-connect.php
                ],
            ]
        ],
    ],
];
{% endhighlight %}

### Create an API and a Service

This part is fairly straightforward. Either follow the official documentation for creating rest services, or create
a simple REST service for test purposes, which is what I'm going to do here.

![Test API Example Screenshot]({{site.url}}/images/test-api-example.png)

I created an API called Test with a REST service called Test. All the Test service does is return all PTFs with
updates available when a GET request is sent for a collection.

So if we call `http://api.ibmiserver.com/test` through a service like Postman, we should get something like:

{% highlight json %}
{
  "_links": {
    "self": {
      "href": "http://test.api.t-r.com/test"
    }
  },
  "_embedded": {
    "test": [
      {
        "ptf_group_currency": "PSP INFORMATION NOT AVAILABLE",
        "ptf_group_id": "SF99145",
        "ptf_group_title": "PERFORMANCE TOOLS",
        "ptf_group_level_installed": 9,
        "ptf_group_level_available": null,
        "ptf_group_last_updated_by_ibm": null,
        "ptf_group_release": "V7R1M0",
        "ptf_group_status_on_system": "INSTALLED"
      },
      {
        "ptf_group_currency": "PSP INFORMATION NOT AVAILABLE",
        "ptf_group_id": "SF99362",
        "ptf_group_title": "BACKUP RECOVERY SOLUTIONS",
        "ptf_group_level_installed": 54,
        "ptf_group_level_available": null,
        "ptf_group_last_updated_by_ibm": null,
        "ptf_group_release": "V7R1M0",
        "ptf_group_status_on_system": "INSTALLED"
      }
    ]
  },
  "total_items": 2
}
{% endhighlight %}

### Poor Man's REST

Instead of relying Entity and Collection definitions, which would be the proper way, I have used a barebones approach
to creating RESTful services when on the IBM i. This is largely due to the data I deal with daily, which is
non-normalized and has column names that sometimes use special characters. Let's take a look at the
Resource and ResourceFactory for this service in case others need to take this same approach.

{% highlight php %}
<?php
// module/Test/src/V1/Rest/Test/TestResourceFactory.php
namespace Test\V1\Rest\Test;

class TestResourceFactory
{
    /**
     * This is so PHPStorm knows what type of Object $services is.
     * @param \Zend\ServiceManager\ServiceManager $services
     * @return TestResource
     */
    public function __invoke($services)
    {
        // Grab the ibmdb service we created earlier to define our database
        $db = $services->get('ibmdb');

        // Inject that database into TestResource for use in the Test REST service.
        return new TestResource($db);
    }
}
{% endhighlight %}

{% highlight php %}
<?php
// module/Test/src/V1/Rest/Test/TestResource.php
namespace Test\V1\Rest\Test;

use ZF\ApiProblem\ApiProblem;
use ZF\Rest\AbstractResourceListener;

class TestResource extends AbstractResourceListener
{
    /**
     * Define $db variable
     * @var \Zend\Db\Adapter\Adapter $db
     */
    private $db;

    public function __construct($db) {
        // Initiate $db variable with what is injected from the factory
        $this->db = $db;
    }

    /**
     * Fetch all or a subset of resources
     *
     * @param  array $params
     * @return ApiProblem|mixed
     */
    public function fetchAll($params = [])
    {
        $sql = <<<SQL
SELECT * FROM SYSTOOLS.GROUP_PTF_CURRENCY
ORDER BY PTF_GROUP_LEVEL_AVAILABLE - PTF_GROUP_LEVEL_INSTALLED DESC
SQL;

        $resultSet = $this->db->query($sql, []);

        return $resultSet->toArray();
    }
}

{% endhighlight %}

While it isn't ideal to be running raw sql in the Resource, sometimes we don't have much choice, and I wanted
to demonstrate a simple way to get started on the IBM i. That's it for now. Stay tuned for
Apigility + OAuth2 on the IBM i and how to digest these services with Angular2.

gha_language: JavaScript


text:
### A simple visualization of FX data provided by different banks.

In the dashboard, we are showing what is the `ASK` and `BID` prices and sizes for selected banks. We are also showing the change in the spread over the time for the selected banks. You can also see the raw data which we have used to create such plots by clicking on `Data` tab.

Contact us for more details.

repository: Pirimid/r-shiny-reports-samples

repo_name: Pirimid/r-shiny-reports-samples


text:
# BS-Horizon Repository

## Description
BS-Horizon is a Fortran77 program for determination of an optimal geologic surface using both elevation data and strike-dip data.

## Input data format
Elevation data and strike-dip data are available. File format of each data are as follows.

### 1. Elevation data
#### Format =>  id, x, y, z, lm
lm=0 gives equality constraint that the surface passes through the point. lm=-1 and lm=1 give inequality constraint that the surface passes under the point or above the point respectively. "0, 9e9, 9e9, 9e9, 9" is required in final line.
Example ( elevation.xyz ):
```
1,7,16,20,0
2,19,80,37,1
3,23,43,42,0
4,87,23,45,-1
5,84,85,55,1
0,9e9,9e9,9e9,9
```

### 2. Strike-dip data
#### Format =>  id, x, y, z, trend, dip
Strike-dip information is given as *trend* and *dip*. The *trend* is an azimuth direction of maximum slope of the surface measured clockwise from north. The *dip* is a slope angle of the surface. "0, 9e9, 9e9, 9e9, 9e9, 9e9" is required in final line.
Example ( dip.xyz ):
```
1,13,82,32,285,40
2,28,35,45,220,30
3,34,8,35,200,40
4,47,83,48,285,30
5,77,93,50,300,20
6,64,59,65,220,20
7,72,14,39,170,40
8,90,47,45,150,30
0,9e9,9e9,9e9,9e9,9e9
```

## Usage
### 1. How to complie BS-Horizon
Compile with GFortran compiler.

```
gfortran bs_horizon.f -o bs_horizon.out
```
### 2. How to run BS-Horizon
Following is an example of surface estimation ( DEM generation ) using equality/inequality elevation data and strike-dip data. As for each parameters, please see Nonogaki *et al.* (2008).

**Step 1.** Run "bs_horizon.out".
```
./bs_horizon.out
```

**Step 2.** Set file names of elevaiton data and strike-dip data (optional).
```
#####Data input#####
File name for elevation data   = elevation.xyz
Do you have trend & dip data ?
                : 1(yes),0(no) = 1
File name for trend & dip data = dip.xyz
```

Basic information of input data is displayed.
```
#####Data information#####
Number      : NH(Height data)      =       5
            : ND(Trend & dip data) =       8
Data area   : x(min),x(max)        =      7.0000     90.0000
            : y(min),y(max)        =      8.0000     93.0000
            : z(min),z(max)        =     20.0000     55.0000
```

**Step 3.** Set calculation range and the number of division which gives the number of knots used for B-spline definition.
```
#####Calculation region#####
Calculation region : x(min),x(max) = 0,100
                   : y(min),y(max) = 0,100
Number of division   Mx,My must be =<200
                   : Mx,My         = 50,50
```

**Step 4.** Set calculation penalty alpha, penalty gamma, m1 and m2 parameters. To use inequality elevation data, alpha(min/max) and the number of iteration are also required.
```
#####Calculation parameter#####
Some iteration is required.
Q= J+alpha*R       : alpha(min)    = 1
                   : alpha(max)    = 100
            number of iteration    = 10
R=Rh+gamma*Rd      : gamma         = 10000
J=m1*[(fx)**2+(fy)**2]+
  m2*[(fxx)**2+2(fxy)**2+(fyy)**2]
                   : m1,m2         = 0,1
```

Calculation results (the values of functionals) in each step are displayed.
```
#####Number of constraints#####
elevation constraints : NH         =      5
    slope constraints : ND         =      8
#####Estimation result#####
iteration=   1  alpha= 0.10000E+01  gamma= 0.10000E+05
------------------------------------------------------
H : data =     2  Rh = 0.10501E+00  Error= 0.32405E+00
D : data =     8  Rd = 0.34521E-06  Error= 0.58755E-03
------------------------------------------------------
Jx = 0.43547E+00  Jy = 0.71844E+00
Jxx= 0.10977E+01  Jxy= 0.23049E+00  Jyy= 0.14591E+01
J1 = 0.11539E+01  J2 = 0.30177E+01
------------------------------------------------------
Q  = 0.31262E+01  J  = 0.30177E+01  aR = 0.10846E+00

#####Number of constraints#####
elevation constraints : NH         =      5
    slope constraints : ND         =      8
#####Estimation result#####
iteration=   2  alpha= 0.16681E+01  gamma= 0.10000E+05
------------------------------------------------------
H : data =     2  Rh = 0.48707E-02  Error= 0.69790E-01
D : data =     8  Rd = 0.79084E-07  Error= 0.28122E-03
------------------------------------------------------
Jx = 0.57872E+00  Jy = 0.82724E+00
Jxx= 0.82259E+00  Jxy= 0.19538E+00  Jyy= 0.11207E+01
J1 = 0.14060E+01  J2 = 0.23341E+01
------------------------------------------------------
Q  = 0.23435E+01  J  = 0.23341E+01  aR = 0.94440E-02

---

#####Number of constraints#####
elevation constraints : NH         =      5
    slope constraints : ND         =      8
#####Estimation result#####
iteration=  10  alpha= 0.10000E+03  gamma= 0.10000E+05
------------------------------------------------------
H : data =     2  Rh = 0.14621E-05  Error= 0.12092E-02
D : data =     8  Rd = 0.22088E-10  Error= 0.46998E-05
------------------------------------------------------
Jx = 0.58121E+00  Jy = 0.83053E+00
Jxx= 0.82845E+00  Jxy= 0.19492E+00  Jyy= 0.11249E+01
J1 = 0.14117E+01  J2 = 0.23432E+01
------------------------------------------------------
Q  = 0.23434E+01  J  = 0.23432E+01  aR = 0.16830E-03
```

**Step 5.** Input file name of DEM, output range, the number of grids. Optimal surface file can be saved (optional).
```
#####Output result to files#####
File name for DEM or no (skip)     = result.grd
Output region      : x(min),x(max) = 0,100
                   : y(min),y(max) = 0,100
Number of grid       Nx,Ny must be =< 1001
                   : Nx,Ny         = 201,201
File name for optimal surface
                      or no (skip) = result.opt
```

**Step 6.** Select next work ( To finish, type zero ).
```
#####Next work#####
Change input data            = 1
Change calculation region    = 2
Change calculation parameter = 3
Output result to files       = 4
End                          = others
                   next work = 0
```

**Result**

<img src="./result.png" alt="result" width="300" height="300">

## Reference
Nonogaki S, Masumoto S and Shiono K (2008) Optimal Determination of Geologic Boundary Surface Using Cubic B-Spline. *Geoinformatics*, vol.19, no.2, pp.61-77 (in Japanese with English abstract). DOI: <https://doi.org/10.6010/geoinformatics.19.61>

repository: S-Nonogaki/BS-Horizon

repo_name: S-Nonogaki/BS-Horizon


text:
## Deployment

Openshift takes care not only of keeping application alive but it also make sure to distribute the pods across [nodes](https://docs.openshift.com/enterprise/3.0/architecture/infrastructure_components/kubernetes_infrastructure.html#node), this is not different for RHSSO.

![high level view](https://github.com/cesarvr/keycloak-examples/blob/master/docs/scaling-pod-up.png?raw=true)

> Here we see an Openshift configuration with 3 pods evenly distributed across nodes.

Once RHSSO containers are up and running and has pass the [liveness probe check](), they get automatically subscribed to the [Openshift service](https://docs.openshift.com/enterprise/3.0/architecture/core_concepts/pods_and_services.html#services) load balancer table which start directing traffic to them.

![traffic from service](https://github.com/cesarvr/keycloak-examples/blob/master/docs/service-dns.png?raw=true)

> The load balancing is handled by the Openshift service abstraction.

## Discovery

Then RHSSO use a discovery algorithm to locate nearby RRHSSO instance members (pods) by using the [JGroups DNS_PING protocol](http://www.jgroups.org/manual4/index.html#_dns_ping), this algorithm basically works by fetching a list of active pods from the Openshift service.

Once the RHSSO discover surrounding instances then it perform the [synchronization of sessions, caches. etc.](https://www.keycloak.org/docs/3.0/server_installation/topics/cache.html) using JGroups/Inifinispan API's for pod intra-communication.

## Distributed Cache

![sessions](https://github.com/cesarvr/keycloak-examples/blob/master/docs/sessions.png?raw=true)

RHSSO implement the concept of cache owners, it basically elect a pod or pods as the gatekeepers for the state of the session, if this owner crash then users in the system will need to re-authenticate.

By default session owners in Openshift is configure for only 1 owner which in some cases is not enough, if you want to increase this number just [read the Customizing RHSSO Container guide.](https://github.com/cesarvr/keycloak-examples/tree/master/modifying-keycloak-cfg#customizing-rhsso-container)

## Persistence

![](https://github.com/cesarvr/keycloak-examples/blob/master/docs/persistence.png?raw=true)

In addition to sessions RHSSO use another layer of storage for persistent data store entities such as Realms and Users. This layer is managed by the [Wildfly DataSource Subsystem](https://docs.jboss.org/author/display/WFLY10/DataSource+configuration).

The RHSSO image comes with support out-of-the-box for the following drivers:
 - [MySQL](https://access.redhat.com/documentation/en-us/red_hat_single_sign-on/7.2/html/server_installation_and_configuration_guide/database-1#database_configuration)
 - [PostgreSQL](https://www.postgresql.org/)
 - [MONGODB](https://www.mongodb.com/) (Driver is present, but not documented).

## More Info

For more info:

- [Testing RHSSO Deployment In Openshift](https://github.com/cesarvr/keycloak-examples/tree/master/robot)

- [Keycloak caches configuration](https://www.keycloak.org/docs/3.0/server_installation/topics/cache.html)
- [Data replication & Failover](https://www.keycloak.org/docs/3.0/server_installation/topics/cache/replication.html) This basically say that Keycloak in Openshift elect only one pod to be the owner of the sessions. For more info on how to overcome this limitation see [Customizing RHSSO Container](https://github.com/cesarvr/keycloak-examples/tree/master/modifying-keycloak-cfg).

repository: cesarvr/keycloak-bible-openshift

repo_name: cesarvr/keycloak-bible-openshift


text:
---
navtitle: shy
---

# Metadata `shy`

The `shy` metadata disables modification of the parent action [status](/current/usages/status/) depending on the child action status where `shy` is activated.

* Type: `boolean`
* Default: `false`

By default, the status of an action will be `true` if at least one of the child action has a status of `true`.

Sometimes, some child actions are not relevant to indicate a change of the parent action status. There are multiple reasons for this. For example, a child action has no impact, like checking prerequisites, or the change of the parent status is assumed by another sibling action.

## Usage

The `shy` metadata is a boolean. The value is `false` by default. Set the value to `true` if you wish to activate the metadata.

`embed:metadata/shy/samples/usage.js`

### Status in action's output

The action's output contains the status of the execution no matter if the `shy` metadata is activated or not.

`embed:metadata/shy/samples/output.js`

repository: LudoSouthPigalle/node-nikita

repo_name: LudoSouthPigalle/node-nikita


text:
---
layout: post
title:  Basic Gradle Awesomeness
date:   2016-07-20 15:08:11
categories: Android
subclass: 'post'
navigation: True
logo: 'assets/images/ghost.png'
---

Want to hide hardcoded constants like URLs, API keys and other credentials? Gradle has a great place for these.

Below is a slightly reduced build.gradle (app) file that I use.

```language=gradle
apply plugin: 'com.android.application'

android {
   signingConfigs {
       debug {
           keyAlias 'debugAlias'
           keyPassword 'password'
           storeFile file('../.debug.jks')
           storePassword 'password'
       }
       release {
           keyAlias 'releaseAlias'
           keyPassword 'releasePassword'
           storeFile file('../release.jks')
           storePassword 'releasePassword'
       }
   }
   compileSdkVer ...
   defaultConfig { .... }
   buildTypes {
       debug {
           debuggable true
           signingConfig signingConfigs.debug
           buildConfigField 'String', 'SERVER_URL', '"DEV_API.EXAMPLE.COM"'
       }
       release {
           debuggable false
           signingConfig signingConfigs.release
           buildConfigField 'String', 'SERVER_URL', '"API.EXAMPLE.COM"'
       }
   }
   buildTypes.each {
       it.buildConfigField 'int', 'DB_VERSION', '3'
   }
}
dependencies { ... }
```

### Why put constants in build.gradle rather than in a resources folder?

During the build process, the constants listed here will actually be built into the resources files, so why do it?

The /res folder to me stands for constants like strings, dimensions, assets and layouts that don't change. I like to put important constants that 'could' change per app release in the build.gradle file.

During an app release/update process, we come to the build.gradle file in order to update the versionCode and versionName. Automatically I can see `DB_VERSION` constant and decide whether it also needs to change too.

### Access build.gradle values at runtime

Values listed in the build.gradle folder are accessed in the app using the BuildConfig class.

```language=java
private Database(Context context) {
    super(context, DATABASE_NAME, null, BuildConfig.DB_VERSION);
}
```

### Build Types

You can also change the gradle values depending on build target. As shown in the sample file above, there are different `SERVER_URL`s for release and debug build targets. This can be great for having separate dev, staging and production urls - just build the app in the corresponding build type and its all gravy!

### Build Flavours

*Not listed, will touch on it soon*


text:
# Welcome to Deep Tinker!

## To Get Started:

* [Create an account](https://developer.mbed.org)
* [Choose a board](https://developer.mbed.org/platforms/Microbit/)
* [Programming environment](https://developer.mbed.org/compiler)

## What is the BBC micro:bit?
The micro:bit is an open development board that allows you to run code on it and have access to all the hardware. It can be used to make all sorts of things, from robots to musical instruments -- wherever your imagination takes you. It's packed with a whole lot of features, a few of which we'll be using today to detect when a friendly micro:bit is nearby:

#### LEDs
The LEDs on the front form a 5 x 5 grid. They can be set to on/off and the brightness can be controlled.

If you turn your micro:bit over, you'll also see a yellow LED called the status LED. It flashes yellow when the system wants to tell the user that something has happened.

#### Buttons
Buttons A and B are a form of input. The micro:bit can detect either of its two buttons being pressed and un-pressed and be programmed to act on that or send the information to another device.

Button R on the back of the micro:bit is a system button. When you have downloaded and run your code onto your BBC micro:bit, press Button R to restart and run your program from the beginning.

#### Bluetooth
You will see a labelled BLE ANNTENA on the back of your micro:bit. The micro:bit is a peripheral device which can talk to a central device like a smart phone or tablet that has Bluetooth Low Energy (BLE). The BBC micro:bit can send signals and receive signals from a central device so another BLE device can control the micro:bit or the micro:bit can control another BLE device. Bluetooth Low Energy is just a power-friendly version of Bluetooth wireless technology.

## Programming the BBC micro:bit
The micro:bit can be connected to your computer or device with a micro USB. When you plug your micro:bit into your computer, it shows up as a mass storage device labeled MICROBIT. Data can be sent and received between the micro:bit and the computer so programs can be downloaded from Windows and Macs onto the micro:bit via USB data connection.

The way we'll do this today is by dragging and dropping HEX files to the enumerated MICROBIT. Intel HEX is a file format that conveys binary information in ASCII text form and is commonly used for programming microcontrollers.

#### Hello, Blinky!

In this module, we will:

* Make a single LED light up
 * Put it in a loop – toggle periodically
 * Change things up -- create our own images!

Let's get started

# Display a single LED

We'll use the `MicrobitImage` class to help us light up an LED here. Images are a good way to create icons and emojis in your code. We just create them like a variable, but provide some additional details that the `MicrobitImage` constructor requests.

The constructor we will use to create our `MicrobitImage` takes three inputs: the first two arguments represent the width and height of the image, and the last argument is a 2D array representing the image. Armed with this information, it’s possible to create a new image like this:

```
#include "MicroBit.h"

//Create an instance of the Microbit class
MicroBit uBit;

const uint8_t image_arr[] {
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 1, 0, 0
    };

int main() {
    //Initialize the microbit runtime
    uBit.init();

    MicroBitImage easyImage(5, 5, image_arr);

    while(1)
        uBit.display.print(easyImage);
}
```

When you click compile, the compiler converts the source code to machine code and outputs it into a HEX file. Before we flash the code onto our device by importing the file to the enumerated MICROBIT, let's go ahead and take a look at the contents of the generated HEX file.

#### Flash!

Drag and drop your HEX file onto the micro:bit.

#### Blinking

If we want the LED to blink, we need to change the `while()` loop to overlay a blank image on top of the existing one.

```
while(1) {
        uBit.display.print(onImage);
        uBit.display.print(offImage);
    }
```

#### Playtime

Modify the `image_arr[]` to change your image. Here, I've chosen to print a smiley face.

```
const uint8_t smile_arr[] {
        0, 1, 0, 1, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        1, 0, 0, 0, 1,
        0, 1, 1, 1, 0
    };

```

If you'd prefer to display a scrolling image instead of a static one, replace `uBit.display.print(easyImage)` with `uBit.display.scroll(easyImage, 80)`.

# Micro:bit Button Press Events

Often times, you need your program to hang around waiting for something to happen before it responds. In our goal for this workshop, it's going to be detecting a *friendly* micro:bit. Before we jump right to the end, let's learn how to detect that an event has occured by simulating some input event. The most obvious means of input on the micro:bit are its two buttons, labelled A and B.

The `MicroBitMessageBus` records which events your program is interested in, and delivers those `MicroBitEvents` to your program as they occur through the `MicroBitMessageBus` `listen` function. This lets you attach a callback to a function when a specified event (or events) occur.

To find out when Button A is clicked or when Button B is clicked, we write some code like this:

    #include "MicroBit.h"

    MicroBit uBit;

    void onButtonA(MicroBitEvent) {
        uBit.display.scroll("A", 80);
        uBit.sleep(1000);
    }

    void onButtonB(MicroBitEvent) {
        uBit.display.scroll("B", 80);
        uBit.sleep(1000);
    }

    int main() {
        // Initialise the micro:bit runtime.
        uBit.init();

        // Register to receive events when any buttons are clicked, including the A+B virtual button (both buttons at once).
        uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_DOWN, onButtonA);
        uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_DOWN, onButtonB);

        // We're done, so just enter a power efficient sleep while we wait for an event.
        while (1) {
            uBit.sleep(10000);
        }
    }

Now, whenever the `MICROBIT_BUTTON__DOWN` event is raised by MICROBIT_ID_BUTTON_A, your code inside function onButtonA will be automatically run.

# Radio

#### Medium - send information over a network
The micro:bit comes with a 2.4GHz radio module primarily designed to run the Bluetooth Low Energy (BLE) protocol. However, it can also be placed into a much simpler mode of operation that allows simple, direct micro:bit to micro:bit communication.

#### Datagram
To write our radio enabled application, we will be using the `MicroBitRadioDatagram` class. It lets you easily send and receive up to 32 bytes of data at a time. This data can be provided as array of bytes, a text string, or a buffer. We will use the `uBit.radio.datagram.send` function to send data. Any other micro:bits in range will detect the transmitted packet, and make the packet available through the `uBit.radio.datagram.recv` function.

Any micro:bits receiving a datagram packet will also raise a `MICROBIT_RADIO_EVT_DATAGRAM` event to indicate that some data is ready to be read.

#### Addressing
The radio module allows you to specify two pieces of information: an address and a group. The address is like a postal address whereas a group is like a specific recipient at the address. The important thing is the radio will filter out messages that it receives that do not match your address and group. As a result, it’s important to pre-arrange the address and group your application is going to use.

Our example uses the micro:bit radio to show if another micro:bit running the same code is nearby. Each micro:bit is periodically broadcasting a group name, and listening to see if another micro:bit in that group is also in-range. When another micro:bit in the same group is detected, the display of the detecting micro:bit will show a filled-in heart shape. Otherwise, the display will show an empty heart shape.

```
// Have we seen a friend recently?
uint8_t friend_seen = 0;

// Are we currently sending out messages?
uint8_t broadcast = 1;

/* We have a group name, and if any micro:bit is in range and in the group
 * then the others will see it.
 */
const char group_name[] = "mHUB";

const uint8_t smile[] {
        0, 1, 0, 1, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        1, 0, 0, 0, 1,
        0, 1, 1, 1, 0
    };

const uint8_t frown[] {
        0, 1, 0, 1, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 1, 1, 1, 0,
        1, 0, 0, 0, 1
    };

const uint8_t heart[] {
        0, 1, 0, 1, 0,
        1, 0, 1, 0, 1,
        1, 0, 0, 0, 1,
        0, 1, 0, 1, 0,
        0, 0, 1, 0, 0
    };

MicroBitImage smileImg(5, 5, smile);
MicroBitImage frownImg(5, 5, frown);
MicroBitImage heartImg(5, 5, heart);

/* We send messages when people press buttons 'A' and 'B'.
 * At the moment, all micro:bits listening for messages
 * will see these and can respond to them
 */
void onButtonA(MicroBitEvent)
{
    uBit.radio.datagram.send("1");
}

void onButtonB(MicroBitEvent)
{
    uBit.radio.datagram.send("2");
}

void onData(MicroBitEvent)
{
    ManagedString recdString = uBit.radio.datagram.recv();

    if (recdString == "1")
        uBit.display.print(smileImg);

    if (recdString == "2")
        uBit.display.print(frownImg);

    /* For detecting the presence of our friend, we require them to be sending
     * the same group name as we are in
     */
    if (recdString == group_name) {
        // We can make this larger to allow more missed packets
        friend_seen = 3;
    }
}

int main() {
    //Initialize the microbit runtime
    uBit.init();
    uBit.radio.enable();

    //Setup button handlers to send data
    uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_EVT_ANY, onButtonA);
    uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_EVT_ANY, onButtonB);

    //Setup a hander to run when data is received
    uBit.messageBus.listen(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, onData);

    while(1) {
        if (friend_seen) {
            uBit.display.print(heartImg);
            friend_seen -= 1;
        } else {
            uBit.display.print(frownImg);
        }
        if (broadcast) {
            uBit.radio.datagram.send(group_name);
        }
        uBit.sleep(1000);
    }
}
```

## Challenge

Make only certain microbits respond to messages. Work with your partner to figure out how to do this. Instructors will walk around to offer guidance.

repository: conduit-labs/deep-tinker

repo_name: conduit-labs/deep-tinker