Coder Social home page Coder Social logo

etclabs / rdmnet Goto Github PK

View Code? Open in Web Editor NEW
37.0 18.0 11.0 3.66 MB

Implementation of ANSI E1.33

Home Page: https://etclabs.github.io/RDMnetDocs

License: Apache License 2.0

C++ 43.25% C 53.87% CMake 2.17% Python 0.52% Shell 0.12% XSLT 0.05% Batchfile 0.03%
lighting protocol network configuration entertainment

rdmnet's Introduction

RDMnet

RDMnet is an ANSI standard for entertainment technology by ESTA for transmission of RDM over IP networks. RDMnet leverages and extends the widely-adopted RDM message set and provides a standard method for configuring both IP-based entertainment equipment and interfaces between IP and DMX512 (commonly referred to as gateways).

About this ETCLabs Project

RDMnet is official, open-source software developed by ETC employees and is designed to interact with ETC products. For challenges using, integrating, compiling, or modifying this software, we encourage posting on the issues page of this project.

Before posting an issue or opening a pull request, please read the contribution guidelines.

Repository Contents

This repository contains a C-language library for core RDMnet communication. It also contains example applications that demonstrate the roles of Components in RDMnet:

  • rdmnet_controller_example: A Qt-based GUI application which does basic discovery, display and configuration of RDMnet Components.
  • rdmnet_broker_example: A console application which implements an RDMnet Broker.
  • rdmnet_device_example: A console application which implements an RDMnet Device.
  • rdmnet_gateway_example: A console application which implements an RDMnet Gateway, affectionately referred to as the "Fakeway". Uses ETC Gadget 2 devices to simulate gateway ports.
  • llrp_manager_example: A console application which implements a basic LLRP Manager.

The applications are available as a binary package on the Releases page.

The example applications currently support Microsoft Windows, macOS, and Linux, and are built using CMake. In addition to these platforms, the RDMnet library also supports any plaform targeted by EtcPal, including embedded RTOS platforms such as FreeRTOS.

Building

For instructions on building the RDMnet library and applications, as well as an RDMnet overview and in-depth documentation, please see the documentation.

Future Plans

This library is maintained by ETC. This open-source implementation of an industry standard is intended to encourage adoption of RDMnet throughout the entertainment industry. The code is licensed under the Apache License 2.0, which allows usage of this library in commercial and/or closed-source applications.

The current prototypes are mostly compliant with the current standard version, with a few exceptions:

  • The Broker library has no RDM responder functionality and does not implement an LLRP Target
  • EPT is not implemented
  • The "Request Dynamic UID Assignment" and "Fetch Dynamic UID Assignment List" Broker messages are not yet implemented

Standards Version

The current version of this repository implements ANSI E1.33-2019, published in August of 2019. You can download the standard document for free from the ESTA TSP downloads page.

Quality Gates

Code Reviews

  • At least 2 developers must approve all code changes made before they can be merged into the integration branch.
  • API and major functionality reviews typically include application developers as well.

Automated Testing

  • This consists primarily of unit tests covering the individual API modules.
  • Some integration tests have also been made.

Automated Style Checking

  • Clang format is enabled โ€“ currently this follows the style guidelines established for our libraries, and it may be updated from time to time. See .clang-format for more details.
  • Non-conformance to .clang-format will result in pipeline failures. The code is not automatically re-formatted.

Continuous Integration

  • A GitLab CI pipeline is being used to run builds and tests that enforce all supported quality gates for all merge requests, and for generating new library builds from main. See .gitlab-ci.yml for details.

Automated Dynamic Analysis

  • ASAN is currently being used when running all automated tests on Linux to catch various memory errors during runtime.

Revision Control

RDMnet development is using Git for revision control.

License

RDMnet is licensed under the Apache License 2.0. RDMnet also incorporates some third-party software with different license terms, disclosed in ThirdPartySoftware.txt in the directory containing this README file.

rdmnet's People

Contributors

bhair avatar christianreese avatar devindeneault avatar nwagner avatar peternewman avatar richardtea avatar samkearney avatar vanvught 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

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

rdmnet's Issues

Library does not build on Linux

Describe the bug
Build error when trying to build on Linux, this looks to be because of a missing header file.

RDMnet/src/rdmnet/discovery/avahi/rdmnet_disc_avahi.c:30:37: fatal error: rdmnet/discovery/common.h: No such file or directory
compilation terminated.
src/rdmnet/CMakeFiles/RDMnet.dir/build.make:322: recipe for target 'src/rdmnet/CMakeFiles/RDMnet.dir/discovery/avahi/rdmnet_disc_avahi.c.o' failed
make[2]: *** [src/rdmnet/CMakeFiles/RDMnet.dir/discovery/avahi/rdmnet_disc_avahi.c.o] Error 1
CMakeFiles/Makefile2:717: recipe for target 'src/rdmnet/CMakeFiles/RDMnet.dir/all' failed
make[1]: *** [src/rdmnet/CMakeFiles/RDMnet.dir/all] Error 2
Makefile:140: recipe for target 'all' failed
make: *** [all] Error 2

To Reproduce
Steps to reproduce the behavior, e.g.:

  1. Clone repository
  2. Follow instructions to configure and build
  3. See compile failure

Expected behavior
Sucessful compile

Additional context
Just trying to build from Linux command line.
Linux 'uname -a' output:
Linux defiant 4.15.0-72-generic #81~16.04.1-Ubuntu SMP Tue Nov 26 16:34:21 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

llrp_manager_example: Wrong output for Device info -> Product Category

Device info:
  RDM Protocol Version: 1.0
  Device Model ID: 32552 (0x7f28)
  Product Category:
    Coarse: 127 (0x7f)
    Fine: 255 (0xff)
  Software Version ID: 1568217936 (0x5d791b50)
  DMX512 Footprint: 16
  DMX512 Personality:
    Current: 1
    Total: 1
  DMX512 Start Address: 1
  Subdevice Count: 0
  Sensor Count: 1

Issue is here -> https://github.com/ETCLabs/RDMnet/blob/develop/examples/llrp_manager/src/manager.cpp#L465

etcpal_upack_16b should be used with cur_ptr += 2;

llrp_manager_example : DMX512 Personality: 257 [> 255]

See output from llrp_manager_example {MacOS} below. The DMX512 Personality should be 1 (in my case). Also the DMX512 Personality is a byte (8-bits) field, hence it cannot be > 255.

i 0
Device info:
  RDM Protocol Version: 1.0
  Device Model ID: 32531
  Product Category: 32767
  Software Version ID: 1568128227
  DMX512 Footprint: 16
  DMX512 Personality: 257
  DMX512 Start Address: 1
  Subdevice Count: 0
  Sensor Count: 0

llrp_manager_example: kLlrpCompNonRdmnet defined but not used

The kLlrpCompNonRdmnet is not used in

const char* LLRPManager::LLRPComponentTypeToString(llrp_component_t type)

where it is here ->

/*! Identifies the type of RPT Component with which an LLRP Target is associated. */

Hence I am getting Unknown ->

Handle UID CID Type Hardware ID
0 7ff0:3064d9e5 9183911e-6986-40e8-a6e7-159f7cfd6251 Unknown f4:4d:30:64:d9:e5

where I have set ->

#define LLRP_COMPONENT_TYPE_NON_RDMNET 0xFF

llrp_manager_example segfaults when there are > 200 targets on Linux

Describe the bug
Do a discovery of 201 targets (i.e. target numbers 0-200) and the app segfaults, this happens with either my LLRP target or rdmnet_device_example. This is on my Linux port in #27 .

To Reproduce
Start up 201 targets, e.g. I use supervisor using this config:

[program:etc-llrp]
command=/path/to/etclabs-rdmnet/build/examples/device/rdmnet_device_example
process_name=%(program_name)s_%(process_num)d
numprocs=201
numprocs_start=0
directory=/path/to/etclabs-rdmnet/build
redirect_stderr=true

Run a discovery on the relevant interface.

Adding LLRP Target, UID e574:3b9c35c8, with handle 198
Adding LLRP Target, UID e574:63c59ea4, with handle 199
Adding LLRP Target, UID e574:56ba5400, with handle 200
Segmentation fault (core dumped)

Strace:

Adding LLRP Target, UID e574:53fdca41, with handle 197
Adding LLRP Target, UID e574:6e9d0be1, with handle 198
Adding LLRP Target, UID e574:52257d65, with handle 199
Adding LLRP Target, UID e574:1a63969f, with handle 200
NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000}, NULL)         = 0
nanosleep({0, 100000000},  <unfinished ...>
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)

Looking at Wireshark, it does successfully send out the 0000:000000 to 7fff:ffffffff search twice (but not the third time).

Expected behavior
It to not segfault.

[Question] Support for Android?

Not a bug report, just a question.

I'm currently trying to include RDMnet libraries into a project, and have built the library and included successfully so far for macOS, iOS, and Windows. The last piece I need is to compile RDMnet for Android, and I'm running into two problems:

  1. Build error complaining about uuid/uuid.h not being found. Apparently, this is not included in the C++ NDK used to compile for Android, but is included in the AOSP sources, so I just downloaded from there and dropped it in ./external/EtcPal/include/ just to get the build to succeed.
  2. Build errors complaining about avahi-client/client.h not being found. I understand this is expected for Linux builds, but I'm wondering if this is necessary on Android, as Android has its own "Network Service Discovery". Is this sufficient for mDNS support, or would I need to build avahi-client for Android and include the headers to build?

Thanks for any insight you can provide!

Lack of VECTOR_RPT_STATUS_BROADCAST_COMPLETE handling for NULL_ENDPOINT devices (but probably applies to all devices

Describe the bug
I don't get an RPT Status response from the broker when I send a broadcast or vendorcast message to the NULL_ENDPOINT.

I note your RPT Status docs at https://etclabs.github.io/RDMnetDocs/0.3.0/handling_rdm_commands.html don't seem to mention this case either.

To Reproduce

  1. Run up the example broker
  2. Run up the rdmnet_device_example
  3. Send a broadcast or vendorcast message to the NULL_ENDPOINT of multiple devices
  4. Note that there is no RPT Status message received with a vector of VECTOR_RPT_STATUS_BROADCAST_COMPLETE.

Expected behavior
From the standard, 7.4.7.1 Scope Broadcast certainly allows the message I'm sending.
7.5.3 says "The Broadcast Complete message is sent by a Device or Broker once it has finished transmission of an RDM Command PDU or RPT PDU that is addressed to a broadcast UID."
7.5.3.7 says "A Broadcast Complete message informs a Controller that an RDM Command PDU was successfully sent to at least one Device. Since broadcast messages are inherently unreliable, this does not indicate that all Devices received the broadcast message."

9.2.7 is probably the most explicit on this point "In the case of a broadcast message, the Broker shall then send to the originating Controller a Broadcast Complete RPT Status PDU. If the enclosed RDM Command message is also a broadcast message (though this time for RDM Responders), the Broker should expect to receive Broadcast Complete messages from the Devices that were targeted by the broadcast. These messages should not be forwarded to the originating Controller."

I saw you've got the code to discard the device messages, it just looks like the broker is missing its code to send the controller a status message. From my reading of 9.2.7 that's actually regardless of the endpoint it was targeted at, i.e. it should respond with a status message in all cases once it managed to pass the message onto devices.

Additional context
I'm using the example broker and responder apps. Logging as follows:
2024-03-30 22:01:44.000Z [DBUG] RDMnet Broker: Broadcasting RPT message from Controller 7a70:9d00000a to all Devices from manufacturer e574

Likewise if I do a broadcast:
2024-03-30 22:04:02.000Z [DBUG] RDMnet Broker: Broadcasting RPT message from Controller 7a70:9d00000a to all Devices

Wireshark of the vendorcast packet:

RDMnet
    Packet Identifier: ASC-E1.17
    Data length: 88
    PDU: Root RPT, Src: ce61a768-eade-4739-af5c-841bf7a1477d
        Flags: 0xf0
        Length: 88
        Protocol ID: RDM Packet Transport Protocol (5)
        CID: ce61a768-eade-4739-af5c-841bf7a1477d
        PDU: Request
            Flags: 0xf0
            Length: 65
            RPT Vector: Request (1)
            Source UID: 7a 70 9d 00 00 0a
            Source Endpoint ID: 0
            Destination UID: ff fd e5 74 ff ff
            Destination Endpoint ID: 0
            Sequence Number: 0
            Reserved: 0
            PDU: RDM Command
                Flags: 0xf0
                Length: 37
                RPT Request Vector: RDM Command (1)
                PDU: RDM Start Code
                    Flags: 0xf0
                    Length: 30
                    RDM Command: RDM Start Code (204)
                    Remote Device Management, Dst UID: e574:ffffffff, Src UID: 7a70:9d00000a
                        Sub-start code: 0x01
                        Message length: 25
                        Destination UID: e574ffffffff
                        Source UID: 7a709d00000a
                        Transaction number: 5
                        Port ID: 1
                        Message count: 0
                        Sub-device: 0
                        Message Data Block
                            Command class: Set Command (0x30)
                            Parameter ID: Identify Device (0x1000)
                            Parameter data length: 1
                            Parameter data
                                Identify Device: 0x00
                        Checksum: 0x0813 [correct]
                        [Checksum Status: Good]

Binary packages for Mac OS and Linux

Currently the binary package is limited for the Windows platform only.
My main development environment is Linux with Mac OS as front-end.
Binary packages on Mac OS and Linux is much appreciated.

LLRP_Manager Hangs Discovery is fixed but IP issue

Hello,

The hangs on discovery is fixed but there is another issue, but this time related to IP.
If the fixture IP range is not the same as the network interface the fixture cannot be discovered.

Example:
Fixture 2.168.10.161
Network interface: 192.168.10.161
In this example the fixture is not found which is not correct.

Our implementation is correct as DMXworshop works and Netron CLU as well if we set up the fixture as per example above.

Regards

llrp_manager_example: Hangs on discovery

On Linux...

hip@hip-Alienware-13:~/ext/development/RDMnet/build/examples/llrp_manager$ ./llrp_manager_example
ETC Example LLRP Manager version 0.4.0.2 initializing...
2021-08-12 16:16:09.000+10:00 [INFO] RDMnet: Initializing multicast network interfaces...
Discovered network interfaces:
Handle Address                        MAC               Name
0      127.0.0.1                      00:00:00:00:00:00 lo
1      ::1                            00:00:00:00:00:00 lo
2      192.168.1.49                   34:e6:d7:3e:b6:95 enp2s0
3      fe80::f10f:a22d:2bf7:9a73      34:e6:d7:3e:b6:95 enp2s0
4      172.17.0.1                     02:42:7d:2e:90:a8 docker0
LLRP Manager Commands:
    ?: Print commands
    d <netint_handle>: Perform LLRP discovery on network interface indicated by
        netint_handle
    pt: Print discovered LLRP Targets
    pi: Print network interfaces
    i <target_handle>: Get DEVICE_INFO from Target <target_handle>
    l <target_handle>: Get DEVICE_LABEL from Target <target_handle>
    gi <target_handle>: Get LIST_INTERFACES from Target <target_handle>
    sf <target_handle>: Set FACTORY_DEFAULTS on Target <target_handle>
    si <target_handle>: Toggle IDENTIFY_DEVICE on/off on Target <target_handle>
    sl <target_handle> <label>: Set DEVICE_LABEL to <label> on Target
        <target_handle>
    sr <target_handle>: Set RESET_DEVICE on Target <target_handle>
    sz <target_handle> <interface_id>: Set IPV4_ZEROCONF_MODE
        with Set INTERFACE_APPLY_CONFIGURATION on Target <target_handle>
    m <target_handle>: Get MANUFACTURER_LABEL from Target <target_handle>
    c <target_handle>: Get DEVICE_MODEL_DESCRIPTION from Target <target_handle>
    s <target_handle> <scope_slot>: Get COMPONENT_SCOPE for Scope Slot
        <scope_slot> from Target <target_handle>
    ss <target_handle> <scope_slot> <scope> [ip:port]: Set COMPONENT_SCOPE to
        <scope> for Scope Slot <scope_slot> on Target <target_handle> with
        optional static Broker address ip:port
    q: Quit
d 2
Starting LLRP discovery...
Adding LLRP Target, UID 5000:3c420913, with handle 0

But it never returns...

However, if I use an interface with no targets, like 127.0.0.1, or a IPv6, it finds nothing (as expected) but does return...

hip@hip-Alienware-13:~/ext/development/RDMnet/build/examples/llrp_manager$ ./llrp_manager_example
ETC Example LLRP Manager version 0.4.0.2 initializing...
2021-08-12 16:19:28.000+10:00 [INFO] RDMnet: Initializing multicast network interfaces...
Discovered network interfaces:
Handle Address                        MAC               Name
0      127.0.0.1                      00:00:00:00:00:00 lo
1      ::1                            00:00:00:00:00:00 lo
2      192.168.1.49                   34:e6:d7:3e:b6:95 enp2s0
3      fe80::f10f:a22d:2bf7:9a73      34:e6:d7:3e:b6:95 enp2s0
4      172.17.0.1                     02:42:7d:2e:90:a8 docker0
LLRP Manager Commands:
    ?: Print commands
    d <netint_handle>: Perform LLRP discovery on network interface indicated by
        netint_handle
    pt: Print discovered LLRP Targets
    pi: Print network interfaces
    i <target_handle>: Get DEVICE_INFO from Target <target_handle>
    l <target_handle>: Get DEVICE_LABEL from Target <target_handle>
    gi <target_handle>: Get LIST_INTERFACES from Target <target_handle>
    sf <target_handle>: Set FACTORY_DEFAULTS on Target <target_handle>
    si <target_handle>: Toggle IDENTIFY_DEVICE on/off on Target <target_handle>
    sl <target_handle> <label>: Set DEVICE_LABEL to <label> on Target
        <target_handle>
    sr <target_handle>: Set RESET_DEVICE on Target <target_handle>
    sz <target_handle> <interface_id>: Set IPV4_ZEROCONF_MODE
        with Set INTERFACE_APPLY_CONFIGURATION on Target <target_handle>
    m <target_handle>: Get MANUFACTURER_LABEL from Target <target_handle>
    c <target_handle>: Get DEVICE_MODEL_DESCRIPTION from Target <target_handle>
    s <target_handle> <scope_slot>: Get COMPONENT_SCOPE for Scope Slot
        <scope_slot> from Target <target_handle>
    ss <target_handle> <scope_slot> <scope> [ip:port]: Set COMPONENT_SCOPE to
        <scope> for Scope Slot <scope_slot> on Target <target_handle> with
        optional static Broker address ip:port
    q: Quit
d 0
Starting LLRP discovery...
LLRP Discovery finished.

with strace ./llrp_manager_example I can see it just loops for eternity...

write(1, "        <scope> for Scope Slot <"..., 75        <scope> for Scope Slot <scope_slot> on Target <target_handle> with
) = 75
write(1, "        optional static Broker a"..., 47        optional static Broker address ip:port
) = 47
write(1, "    q: Quit\n", 12    q: Quit
)           = 12
fstat(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
read(0, d 2
"d 2\n", 1024)                  = 4
write(1, "Starting LLRP discovery...\n", 27Starting LLRP discovery...
) = 27
sendto(12, "\0\20\0\0ASC-E1.17\0\0\0\360\0D\0\0\0\n\323\374\271S@\331A\207\273"..., 84, 0, {sa_family=AF_INET, sin_port=htons(5569), sin_addr=inet_addr("239.255.250.133")}, 16) = 84
nanosleep({tv_sec=0, tv_nsec=100000000}, Adding LLRP Target, UID 5000:3c420913, with handle 0
NULL) = 0
nanosleep({tv_sec=0, tv_nsec=100000000}, NULL) = 0
nanosleep({tv_sec=0, tv_nsec=100000000}, NULL) = 0
nanosleep({tv_sec=0, tv_nsec=100000000}, NULL) = 0
nanosleep({tv_sec=0, tv_nsec=100000000}, NULL) = 0
nanosleep({tv_sec=0, tv_nsec=100000000}, NULL) = 0
nanosleep({tv_sec=0, tv_nsec=100000000}, NULL) = 0
nanosleep({tv_sec=0, tv_nsec=100000000}, NULL) = 0
nanosleep({tv_sec=0, tv_nsec=100000000}, NULL) = 0
nanosleep({tv_sec=0, tv_nsec=100000000}, NULL) = 0
nanosleep({tv_sec=0, tv_nsec=100000000}, NULL) = 0
nanosleep({tv_sec=0, tv_nsec=100000000}, NULL) = 0
...
...

...until I kill it.

Fresh clone today and compiles without incident.

Windows example: llrp_manager_example no output

When running the latest example on Windows 10, there is nothing happening:

C:\Program Files\ETC\RDMnet\bin>llrp_manager_example.exe

C:\Program Files\ETC\RDMnet\bin>

Note: I am running Windows 10 in Parallels Desktop on MacOS

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.