Giter Club home page Giter Club logo

knx-iot-stack's Introduction

image

image

image

image

image

image

Introduction

KNX IoT Point API stack is an open-source, reference implementation of the KNX IoT standard for the Internet of Things (IoT). Specifically, the stack realizes all the functionalities of the KNX IoT Point API specification.

Architecture

The responsibilities between the stack and an actual KNX IoT Point API device implementation is depicted in the following diagram:

application vs stack

The project was created to bring together the open-source community to accelerate the development of the KNX IoT Point API devices and services required to connect the growing number of IoT devices. The project offers device vendors and application developers royalty-free access under the Apache 2.0 license.

Stack features

- OS agnostic: The KNX IoT Point API device stack and modules work cross-platform (pure C code) and execute in an event-driven style. The stack interacts with lower level OS/hardware platform-specific functionality through a set of abstract interfaces. This decoupling of standards related functionality from platform adaptation code promotes ease of long-term maintenance and evolution of the stack through successive releases.

PortingLayer

- Porting layer: The platform abstraction is a set of generically defined interfaces which elicit a specific contract from implementations. The stack utilizes these interfaces to interact with the underlying OS/platform. The simplicity and boundedness of these interface definitions allow them to be rapidly implemented on any chosen OS/target. Such an implementation constitutes a "port".

Project directory structure

api/*

contains the implementations of client/server APIs, the resources, utility and helper functions to encode/decode CBOR to/from data points (function blocks), module for encoding and interpreting endpoints, and handlers for the discovery, device and application resources.

messaging/coap/*

contains a tailored CoAP implementation.

security/*

contains resource handlers that implement the security model, using OSCORE.

utils/*

contains a few primitive building blocks used internally by the core framework.

deps/*

contains external project dependencies.

deps/tinycbor/*

contains the tinyCBOR sources.

deps/mbedtls/*

contains the mbedTLS sources.

include/*

contains all common headers.

include/oc_api.h

contains client/server APIs.

include/oc_rep.h

contains helper functions to encode/decode to/from cbor

include/oc_helpers.h

contains utility functions for allocating strings and arrays either dynamically from the heap or from pre-allocated memory pools.

port/*.h

collectively represents the platform abstraction.

port/<OS>/*

contains adaptations for each OS. Platforms:

  • Linux storage folder is created by the make system
  • Windows storage folder is automatic created by the make system. as extra also the stack creates the storage folder. This allows copying of the executables to other folders without having to know which folder to create.
apps/*

contains sample applications.

External Sample Applications

The external sample applications are using CMAKE to pull in the KNX IoT Point API stack

Examples are:

Build instructions

Grab source and dependencies from GitHub using:

git clone --recursive https://github.com/KNX-IOT/KNX-IOT-STACK.git

or use GitLab:

git clone --recursive https://gitlab.knx.org/shared-projects/knx-iot-point-api-public-stack.git

Please check here for build instructions:

Send Feedback

Bugs Issues

knx-iot-stack's People

Contributors

antumushfiq avatar cascodabot avatar ceolin avatar cmarcelo avatar danielius1922 avatar elie-elkhoury avatar frankzrs avatar georgen117 avatar github-actions[bot] avatar iotj avatar iuriimet avatar jimmy-huang avatar jkralik avatar kmaloor avatar ljsachs avatar looksgoood avatar lubo-kistler avatar marktrayer avatar mattiantonini avatar o-andrieiev avatar ramijung avatar rsbells avatar rwells1703 avatar rzr avatar simet avatar skyler84 avatar tiniuclx avatar twonky-andreas avatar wavdbeek avatar webispy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

knx-iot-stack's Issues

13) Client Security implementation

(Add Spake2+)

  • establish secure session to other Device
    • spake 2 exchange (client side)
    • oscore coap request
    • dtls (optional)
  • spake2+ definition
  • use audience & scope to select correct security info (token) for subsequent communication
  • access to ETS with KNX-IOT configuration ETS not available in time

(add client code: python, based on dll)

  • auth

    • subtypes
      • skeleton
      • resources listed in link-format
      • implementation
        • /auth/at
        • /auth/at/
  • wellknown/knx (security related)

    • GET (JSON)
    • POST
      • skeleton
      • reset behaviour
    • subtypes
      • implementation
        • /f
        • /osn
        • /spake
          • parameter exchange
          • credential exchange
          • credential verification
        • /idevid optional: not implemented
        • /ldevid optional: not implemented

~Days: 10

Create KNX-IOT repo

  • rename iotivity in documentation to something else
  • rename iotivity in makefiles/tools to something else

~Days: 0

15) code integration (with security)

Code integration with security

  • spake2+ handshake server
    • step 1
    • step 2
    • step 3
    • new field for communicating kid (new)
  • spake2+ handshake client
    • step 1
    • step 2
    • step 3
    • new field for communicating kid (new)
  • spake handshake start only in unloaded state
  • enable oscore
    • send message
    • receive message
    • context
      • setup context for sending
      • setup context for receiving
      • context via auth/at info
      • master secret via auth/at info
  • client & server application using stack using spake2+ handshake
  • CI building
  • CI testing
  • cleaning of mbedtls patches
  • removal of OCF security resources (after implementing KNX security)
    • removed
      • cred
      • cert
    • code clean up with compile directives
  • removal of OCF Device discovery resources (oic/d oic/p oic/res)
  • application behaviour (callbacks)
    • device reset
    • device restart
    • device factory config
    • set device host name
    • software update
    • gateway interception of receiving s-mode messages

rework tasks due to spec changes (spec completion end march)

  • auth/at : tokens rework
    • coap_dtls , coap_oscore as integer
    • remove kty, renamed as sub for dtls only
    • update resource, more dtls info added
  • cflags as bitset
    • use cflags in sending/receiving table info
    • added interface to use to check incoming/outgoing s-mode messages
    • activate s-mode checks on cflags
  • version number 1.0 to 1.0.0
  • make recipient table optional
  • update list of public (unsecured) resources
  • load state machine changes ==> string to int when it is done (now implemented as strings)
  • iid as integer
  • reset behaviour: e.g. correct handling of value = 2 & 7
  • tables ==> send mechanism change from string array to single integer with byteflags ==> when spec is done
  • add /dev/ipv6 resource (new)
  • add /dev/sa resource (new)
  • add /dev/da resource (new)
  • add /dev/port resource (new)
  • rework spake2plus entry in auth/at entry , e.g. add serial number (is in the spec)
  • oscore sequence number: add new coap mechanism: TBD.
    • new coap header
    • for sender: on reply: answer to originator when header is exists.
    • for receiver: when oscore number is out of sequence
      • use new header in reply, adding some unique info
      • wait on reply with unique info from sender
      • set the tracked oscore sequence number to the received value in step 1
      • oscore sequence number tracking per sending device
      • entry per receiving endpoint
      • entry in list for sending group communication.
      • entry in list for sending normal communication per endpoint
  • rework for group addressing: what is the ULA? question raised to Oskar: is the iid, will be clarified in spec
  • rework for group addressing: what is the port? question raised to Oskar : port is ALL COAP port
  • rework on payloads at least on /dev/xxx e.g. change from value only to object with tag number 1 and value
  • new resources/definitions on usage of Ia (spec changes on 25 march)

~Days: 9

Some doc bugs

py_install_resourceCB:

  • wrong return type documentation

py_issue_requests_s_mode:

  • value_type wrong encoding documentation for "boolean" and "integer"
  • wrong return type documentation

py_exit:

  • wrong return type documentation

17) End2End test work (Final, incl security)

setup:
client on pc --> Pi BR --> PI-KNX device

  • works with own python based client, e.g. based on stack dll
  • works with ETS : ETS will not be finished
  • works with other device/stack
  • check all resources for
    • correct usage of defined interfaces
    • correct usage of dpt info
    • correct usage of content type (cbor/link-format)

miscellaneous tasks:

  • test coverage of library
  • remove make file from linux/port
  • add gtests to cmake
  • add warning == error to cmake

coding wrap up tasks:

  • wellknown/core paging of the # entries (not yet needed, block wise is working)

  • add adding function to listen on group addresses to porting layer

    • use function at start up
  • multicast groups

    • add function to create multicast address from group address
    • function to traverse group object table and register the address
    • use function to send s-mode message to multi cast group address.
  • add all resources to: oc_core_get_resource_by_uri(const char *uri, size_t device) (not used yet)

  • check size of url (limited at 30 chars)

    • group object table
    • recipient table
    • publisher table
  • check whether to send an s-mode message regarding flags by looking at cflags in the group object table

  • check if table entries (group object table) contains urls that belong to the device

  • check whether a s-mode message received needs to be processed by looking at cflags in the group object table

  • cflags behaviour in group object table

    • behaviour of w
    • behaviour of r, doing a response with rp on an r
    • behaviour of i, send out an r for the group at start up
    • behaviour of u, e.g. do a write
    • behaviour of t, e.g. send out an message,
  • /p

    • /p get list /p/x
    • /p post update /p/

clean up tasks:

  • remove ocf interfaces
  • remove ocf defines in resource list (e.g. oic_res) etc.

Working with:
@tiniuclx
@WAvdBeek

~Days: 15

Bind to specific network interface

Currently the library binds to all network interfaces. For ETS, it would be useful to bind to only a specific interface.

Please investigate the options for such an extension.

This is especially useful if also #303 is implemented.

Suggestion: On the ETS API level, this could be another parameter to the ets_start method (meaning would probably depend on OS)

3) Device API Definition

  • add support for query without value
    e.g. ?blah instead of ?blah=value

  • infrastructure - CBOR encoding/decoding

    • investigate how to implement tag value with tag as integer (byte)
      note email send of list of tags that are not mapped to integer values
      • encoding works for maps/arrays if multiple values are returned
      • encoding works for single values
      • decoding works for maps/arrays
      • decoding works for singe values
    • KNX defined data formats (e.g. time/...)
      • will use tiny cbor as is.
  • infrastructure - core link format

    • add/create entries (per line)
      • url
      • rt (multiple e.g. rt="one two three"
      • if (single for now),
      • ct content type of the resource, is now part of resource creation
    • filter on query param
    • paging of the # entries (not yet needed, blockwise is working)
      • moved to stack integration
  • infrastructure - interfaces

    • knx defined interfaces
  • implement mandated data points (resources)
    as skeleton only

  • new type of registration with return content-format

  • functionality to list which resources will be listed

    • listing of resources with link-format response
    • blockwise transfer of data of other responses than OCF-cbor
  • adding new functions to return the correct data type

    • link-format
    • cbor
    • json
  • add filtering to make sure that the callback is only called for the correct type.

~Days: 9

11) End2End test work (no security)

  • module test of new components
    • testing API of parsing cbor with integer keys
    • testing parsing application-link format code
    • testing mapping of new interfaces
    • testing of mapping of LSM states (states as strings)
  • end-to-end test, unsecured
    • create dll on windows
    • create shared object (linux)
      • using python as client to drive the server.
        • app to setup configuration
        • app to issue s-mode command
        • app to reset the device
        • app to discover device via ia
    • testing of persistent storage (python)
      • device ia
      • device pm
      • device loadstate
      • group object table
      • group recipient table
      • group publisher table
    • e-e testing (test sequence in python)
      • device /dev
      • device /a/lsm
    • functional checks (python)
      • retrieval of /f (link-format)
      • retrieval of /f/[rpg] (link-format)
      • adding entry in /f/[rpg]/y (link-format)
      • retrieval of /f/[rpg]/y (cbor)
      • deletion of /f/[rpg]/y (cbor)
    • discover checks (python)
      • all devices e.g. rt=urn:knx:dpa.*
      • devices with specific rt e.g. rt=urn:knx:dpa.353
      • devices with ia e.g. if=urn:knx:ia.5
      • all interfaces e.g. if=urn:knx:if.*"
      • specific interfaces e.g. if=urn:knx:if.s"
      • programming mode e.g.if=urn:knx:if.pm
      • compound filtering actuator datapoint e.g. if=urn:knx:if.a&rt=urn:knx:dpa.353*
      • serial number wildcard: ep=urn:knx:sn.*
      • specific serial number : ep=urn:knx:sn.012346
      • part of group address : d=urn:knx:g.s.[ga]

miscellaneous tasks:

  • function point support
    • list function blocks in ./wellknown/core
  • code for system with broker

~Days: 15

10) EmbedTLS work

  • make sure that all cyphersuites are supported
  • understand KNX-IOT spec wrt to SPAKE2+

~Days: 5

6) Code integration (no security)

  • removal of OCF code

    • removal of unused compile directives
      • WK_CORE
      • OC_SOFTWARE_UPDATE
      • OC_COLLECTIONS_IF_CREATE
      • OC_COLLECTIONS
      • OC_IDD_API
      • OC_BATCH Support
    • removal of OCF Cloud
    • removal of oic/con
    • removal of ocf version handling
    • removal of ocf enums
    • removal of oic/d oic/p todo when security is implemented, e.g. issue 16
    • removal of OCF MNT
    • removal of OCF Collections
    • removal of OCF location tagging
    • removal of unsupported ports
    • initial removal of unsupported example apps in /apps
    • cleaning/updating of example apps
  • integrate all changes into code base

  • improve module testing, with new functionality

  • integrate module test into CI

  • resource behaviour

    • persistent storage (over reboots)
      • Group object table
      • IID
      • IA
    • reset behaviour
      • function to restart device
      • function to reset the device
      • function to remove persistent storage
    • listing resources in a device, end point/rt
      • created infrastructure (e.g. listing mandatory devices)
    • group object table support
      • storage of group info
      • upload group information (function points)
      • mechanics of group support
        • .knx receiving command routed to POST function point to set data (value)
        • api to send command, routing to GET function point to frame data (value)

things to keep:

  • OC_TCP
    can be used for software update (optional)

~Days: 10

SMode Messaging - Gateway callback returns invalid Json as payload

It appears that the Json payload return by the gateway callback triggered when observing SMode is not valid Json due to a missing comma between the “sia” and “s” key value pairs.

Example of a Json payload printed by the python SMode sniffer script:
{ "sia": 3 "s":{ "st": "w" , "ga":2, "value": true } }

Would it be possible to change this?
(likely by changing oc_s_mode_notification_to_json in oc_knx.c)

0) Add CMAKE (pre work)

Add CMake to IoTivity

  • check if this is working on Windows

  • check if this is working on Linux

  • build against openthread (Cascoda-SDK)

    • cascoda SDK gives an IP interface for Thread on a PI
  • add code formatting work flow

  • add work flow to check code formatting

not costed in project
~Days: 3

2) Resource Discovery

  • wellknown/core in Iotivity
    • passing OCF certification
      • query params work
      • not replying if not for us works
      • multicast address on linux/windows
        KNX specific:
  • well-known/core api
    • filtering
      • on rt
      • on if
      • on ep
      • on programming mode: GET coap://[FF03::FD]/.well-known/core?if=urn:knx:pm
      • individual address on the network : GET coap://[FF03::FD]/.well-known/core?if=urn:knx:ia
        note that the return on this request is JSON not linkformat
    • listing resources (e.g. only "application")

~Days: 10

project management

  • finalize contract
  • setting up project reporting
  • weekly report
  • monthly billing

not costed in project
~Days: 0

5) Add mandatory resources

implement mandatory resources

security resources:
#7

optional resources:
#62

  • wellknown/knx

    • GET (JSON)
    • POST
      • skeleton
  • action (a)

    • a/lsm (in knx.c)
      • skeleton
      • GET
      • POST
  • dev

    • subtypes
      • skeleton
      • resources listed in link-format
      • implementation
        • /dev
        • /dev/sn
        • /dev/hwv
        • /dev/fwv
        • /dev/hwt
        • /dev/macaddr
        • /dev/name
        • /dev/model
        • /dev/pm
          • GET
          • PUT
          • persistent storage
            note, receiving the boolean seems to be ok, but it gives an error. to be investigated further
        • /dev/ia
          • GET
          • PUT
          • persistent storage
        • /dev/hostname (GET/PUT)
          • GET
          • PUT
          • persistent storage
        • /dev/iid (GET/PUT)
          • GET
          • PUT
  • fp (function points)

    • subtypes
      • skeleton
      • resources listed in link-format
      • implementation
        • ~~ /fp ~~
        • /fp/g
          • GET link format
          • POST list of data
        • /fp/g/
          • GET & Delete
        • /fp/r
        • /fp/r/
        • /fp/p
        • /fp/p/
  • software update (swu)

    • subtypes
      • skeleton
      • resources listed in link-format
      • implementation
      • note, needs filtering, data of firmware is to large for blockwise transfer (now in spec)
        • /swu
        • /a/swu (push writes to file)
        • /swu/pkgnames
        • /swu/pkgqurl (optional)
        • /swu/pkgbytes
        • /swu/pkgv
        • /swu/update
        • ~~ /swu/update/{filename} (optional) ~~
        • /swu/state
        • /swu/result
        • /swu/maxdefer (optional)
        • /swu/method, Note only PUSH... so some extra code needed.
        • /swu/protocol
  • messaging

    • ./knx

~Days: 17

Bind to specific network interface

Currently the library binds to all network interfaces. For ETS, it would be useful to bind to only a specific interface.

Please investigate the options for such an extension.

This

12) Add security resources

add security resources.
Note, this part implements

  • all mandatory resources

  • parses content

  • frames content

  • no storage of payload (e.g. restart device wipes memory)

  • SPAKE2+

    • /.well-known/knx/spake
  • well-known/knx/idevid

  • .well-known/knx/ldevid

  • /auth/at

    • GET
    • POST
  • /auth/at/kid

    • GET
    • DELETE
  • enable oscore

  • /f/oscore

    • GET
  • /p/oscore/

    • GET
    • PUT
  • a/sen (optional, push for LDevID enrollment)

    • skeleton only
    • POST cbor

Correctness & verification dependent on availability of ETS

~Days: 17

ETS work

various tasks for ETS implementation

  • improve documentation
  • add ets_start/poll/stop functionality, so that the ets code does not start up an thread

add routing through publisher table

routing of multicast addresses throught the publisher table
the publisher table is used for unicast AND multicast (e.g. not clear from the spec)

  • when publisher table has entry for multicast, do the subscription of the multicast addresses, no addresses from the Group object table
  • sending s-mode messages, through the multicast addresses through the publisher recipient table.

Note all infra structure is there but not used.

  • code written
  • check end2end

Correct sample serial numbers

Currently the examples contain serial numbers like "000005". The KNX serial number is however a 12-digit (uppercase) hexadecimal string. The samples should have the first digits set to "00FA" (the namespace reserved for KNX association).

(Storing the serial number internally not as string, but as 48 bit integer might be more effective)

light & building

13 to 18 March 2022
new dates not yet known

not costed in project
~Days: 0

8) Device application

  • example app for testing - simple client
    testing if the stack can sent out CoAP requests

    • on windows
    • on Linux
    • well-known core discoverable
  • example app for testing - simple server
    testing if the stack can receive CoAP requests

    • on windows
    • on Linux
    • well-known core discoverable
  • LSAB - device that can be turned on via datapoint 417.61
    KNX-IOT demo application

    • on windows
    • on Linux
    • well-known core discoverable
    • GET on resource
    • POST on resource
    • receive via multicast group address & handle data
  • LSSB - device that can transmit on via datapoint 421.61
    KNX-IOT demo application

    • on windows
    • on Linux
    • well-known core discoverable
    • GET on resource
    • POST on resource
    • receive via multicast & handle data
    • send data via multicast group address
  • code running on raspberry PI, with chili module as thread REED module

  • setup with PC running client --> Pi BR --> PI-KNX device

~Days: 10

0) prework Add github actions for building

  • Linux target
  • open thread target, e.g. towards Cascoda SDK
    • cascoda SDK gives on a PI an IP interface that can be used to communicate over thread
  • windows target, without thread

~Days: 2

Demo

demo for L&B

  • order materials for demo

    • 3 (in total) setups: 1 for KNX staff, 1 for Cascoda in Office, 1 for Wouter in Ireland
      • 2x Pi as KNX device
        • hats (playotron pimoroni), with buttons and LCD for feedback,
        • USB Chili2d Thread dongle
        • Device as LSSB function block
        • Device as LSAB function block
      • Pi as BR
        • PI hat with Chili
  • border router config

  • device config

    • create configuration to be downloaded to the 2 devices
  • network setup

  • configurable (e.g. download config)

Note: might be reopened, e.g. adding more functionality

not costed
~Days: 0

Multiple stack instances

For ETS use, it would be nice if multiple independent instances of the KNX IoT Stack can be used (also in parallel)

Please investigate the options for such an extension.

Suggestion: On the ETS API level, ets_start could return a handle or pointer which is the passed to all other API methods (and the callbacks).

7) update documentation

  • create github repo for doxygen documentation (e.g. will be public)
  • doxygen (API)
    • check if all functions are documents
    • CI publishing
      • CI is there, but not having all the credentials yet
  • markdown (github.io) for other documentation
    • repo available
      • markdown
      • contents
        • building guide for windows
        • building guide for linux (and Pi)

Note: Doxygen repo is there, but repo is not public, hence no documentation is visible
Note: repo for documentation is available and populated with content in markdown, however repo is not yet public

~Days: 4

4) Client API definition in C

Python test code

https://github.com/WAvdBeek/CoAPthon3

  • add functions to set accept header (linkformat)
  • add functions to set accept header (cbor)
  • functions to parse linkformat
  • functions to show cbor
  • functions to replace json key as integer
    • note python can send integers as keys
  • paging of the # entries (not yet needed, blockwise is working)
  • well-known/core usage as client

C code

  • add functions to set accept header (linkformat)

  • add functions to set accept header (cbor)

  • functions to parse linkformat

    • added test for parser
  • functions to show cbor as json

    • integer keys with quotes e.g. "1", similar as spec
  • ~~functions to replace json key as integer ~~
    not needed

  • ~~paging of the # entries (not yet needed, blockwise is working) ~~
    not needed

  • well-known/core usage as client

  • GET with accept header

  • POST with accept header & content

    • not checked but similar as PUT
  • PUT with accept header & content

  • DELETE with accept header & content

    • not checked but similar as PUT

~Days: 9

9) Client application

  • generic client (agnostic of function)
  • sending data for s-mode

Generic client (python) that can:

  • search for devices through wellknown/core
  • do a get on listed resources with the correct type
  • do a put on resource if interfaces is listed as support of put
    note, requires input in cbor or conversion of data to cbor
  • do a post on resource if interfaces is listed as support of post
    note, requires input in cbor or conversion of data to cbor
  • list the data
    • in link format
    • in cbor
    • in json

python code available :
https://github.com/WAvdBeek/CoAPthon3

~Days: 10

14) Device access control

  • elliptic curve implementation for spake2

    • separate test application
  • spake2 handshake

    • client code
    • server code
    • client & server code have correct handshake, e.g. master key is exchanged
    • rework due to spec change (e.g. alignment with spake2plus draft v7
  • usage of coap vs coaps & oscore security

    • accepting secure connection (oscore)
    • adding flag in endpoint for OSCORE connections
    • recognize oscore in client, e.g set flag on endpoint to connect too
    • recognize oscore in server, e.g. by means of oscore coap headers
  • usage of interfaces, e.g. access control

    • filter out calls that should not happen security wise
      • oscore token should be made available so that the auth/at/ can be found
        • implement aud parsing
        • implement using aud /scope info in selecting correct security info
      • auth/at/ interface comparison with interface of resource.
        • prevent calls happening
    • filter out calls based on interface
  • X509 certificates (e.g. different usage & configuration than OCF)

~Days: 10

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.