Coder Social home page Coder Social logo

hm-pktfwd's Introduction

hm-pktfwd

Helium Miner Packet Forwarder

This is a Python app that uses prebuilt utilities to detect the correct concentrator chip and region, then start the concentrator accordingly.

hm-pktfwd builds off three other repos which each built a portion of the code required to run the packet forwarder.

reset_lgw.sh

reset_lgw.sh is a shared tool that is used on all concentrator chip versions. On sx1301 chips, its is recommended that the script is run before each time the concentrator is started. On chips that use sx1302_hal, the reset script is run automatically when the concentrator starts and is expected to be located in the same directory as the lora_pkt_fwd module.

reset_lgw is used by all concentrators, and inspired by the upstream versions. That said, it is different from the originals, context specific to hm-pktfwd, and moved to this repo to avoid confusion about its intention. Additional context here.

Supported Region Plans

You can typically find the exact region plan you need to use at What Helium Region or on the Helium Miner GitHub repo however the table below provides a rough guide...

Region Plan Region
AS923_1 Most of Asia
AS923_2 Vietnam and Indonesia
AS923_3 Phillipines and Cuba
AS923_4 Israel
AU915 Australia, New Zealand and South America
CN470 China
EU868 Europe, Middle East and some of Africa
EU433 Parts of Africa and Asia
IN865 India and Pakistan
KR920 South Korea
RU864 Russia
US915 North America

Please note:

Region Plan Region
CN779 NOT YET SUPPORTED

Customization

The following environment variables control various aspects of the program's operation.

Variable Default Required Description
VARIANT - Yes See variants
SX1301_REGION_CONFIGS_DIR - Yes Path to sx1301 configs
SX1302_REGION_CONFIGS_DIR - Yes Path to sx1302 configs
UTIL_CHIP_ID_FILEPATH - Yes Path to [chip_id](https://github.com/NebraLtd/sx1302_hal/tree/69811057222f6f9cf8929ebfdb7fc6e36cc2618d/util_chip_id
RESET_LGW_FILEPATH - Yes Path to reset.sh. The same file is used for all sx130x versions.
ROOT_DIR - Yes Directory the app will be run from. Should be the same location. global_conf.json will also be copied here.
SX1302_LORA_PKT_FWD_FILEPATH - Yes Path to built sx1302 lora_pkt_fwd executable.
SX1301_LORA_PKT_FWD_DIR - Yes Directory that contains sx1301 lora_pkt_fwd executables for all SPI buses.
LORA_PKT_FWD_BEFORE_CHECK_SLEEP_SECONDS 5 No Duration after starting lora_pkt_fwd before establishing if it started successfully.
LORA_PKT_FWD_AFTER_SUCCESS_SLEEP_SECONDS 30 No Duration to poll status after concentrator starts successfully.
LORA_PKT_FWD_AFTER_FAILURE_SLEEP_SECONDS 2 No Duration to wait before restarting when concentrator exits with 0. If it exits with code greater than 0, program exits and container restarts.
LOGLEVEL DEBUG No TRACE, DEBUG, INFO, WARN, etc.
REGION_FILEPATH /var/pktfwd/region No Path where hm-miner writes the region.
DIAGNOSTICS_FILEPATH /var/pktfwd/diagnostics No File containing "true" or "false" for whether lora_pkt_fwd is successfully running or not.
AWAIT_SYSTEM_SLEEP_SECONDS 5 No How long app sleeps before starting concentrator.
SENTRY_KEY False No Key for Sentry. Sentry inactive if key is False.
REGION_OVERRIDE False No Region override. eg US915.
BALENA_ID From Balena No Only used with Sentry.
BALENA_APP_NAME From Balena No Only used with Sentry.

Building

Pre built containers

This repo automatically builds docker containers and uploads them to two repositories for easy access:

The images are tagged using the docker long and short commit SHAs for that release. The current version deployed to miners can be found in the helium-miner-software repo.

Manual build

When developing, it is faster to build locally instead of relying on the pre-built container to generate.

# Cross-compile
docker buildx build --platform linux/arm64/v8 --progress=plain -t DOCKERHUB_USER/hm-pktfwd .

# To stop at an intermediary stage
docker buildx build --platform linux/arm64/v8 --progress=plain --target pktfwd-builder -t pktfwd-builder .

# Tag and push image
docker image tag docker.io/DOCKERHUB_USER/hm-pktfwd DOCKERHUB_USER/hm-pktfwd:0.0.X
docker push DOCKERHUB_USER/hm-pktfwd:0.0.X

Testing

Hardware Requirements: An ARM64 based device.

Software Requirements:

With the dependencies installed, do the following:

$ git clone https://github.com/NebraLtd/hm-pktfwd.git
$ cd hm-pktfwd
$ docker build . -t hm-pktfwd

Once you've built the image, we need to do a bit of prep work to mock the environment:

$ mkdir -p /var/pktfwd
$ echo region_eu868 | sudo tee -a /var/pktfwd/region

We're now finally ready to start up the containers using:

$ docker-compose up

hm-pktfwd's People

Contributors

dependabot[bot] avatar ilyastrodubtsev avatar kerrryu avatar kevinwassermann94 avatar marvinmarnold avatar muratursavas avatar posterzh avatar pritamghanghas avatar robputt avatar ryanteck avatar shawaj avatar vpetersson avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hm-pktfwd's Issues

LoRa operational false when no region asserted

 packet-forwarder          BALENA_APP=HELIUM-TESTNET
 packet-forwarder          DIAGNOSTICS_FILEPATH=/var/pktfwd/diagnostics
 packet-forwarder          AWAIT_SYSTEM_SLEEP_SECONDS=5
 packet-forwarder          RESET_LGW_FILEPATH=/opt/sx1302/reset_lgw.sh
 packet-forwarder          UTIL_CHIP_ID_FILEPATH=/opt/sx1302/chip_id
 packet-forwarder          ROOT_DIR=/opt
 packet-forwarder          SX1302_LORA_PKT_FWD_FILEPATH=/opt/sx1302/lora_pkt_fwd
 packet-forwarder          SX1301_LORA_PKT_FWD_DIR=/opt/sx1301
 packet-forwarder  
 packet-forwarder  2021-10-28 17:38:11,713 - [DEBUG] - pktfwd.pktfwd_app - (pktfwd_app.py).set_variant_attributes -- /opt/pktfwd/pktfwd_app.py:(91) - Variant NEBHNT-OUT1 set with reset_pin 38 and spi_bus spidev1.2
 packet-forwarder  2021-10-28 17:38:11,714 - [DEBUG] - pktfwd.pktfwd_app - (pktfwd_app.py).start -- /opt/pktfwd/pktfwd_app.py:(39) - STARTING PKTFWD
 packet-forwarder  2021-10-28 17:38:11,717 - [DEBUG] - hm_pyhelper.miner_param - (miner_param.py).await_spi_available -- /opt/pktfwd-dependencies/hm_pyhelper/miner_param.py:(217) - SPI bus spidev1.2 Configured Correctly
 packet-forwarder  2021-10-28 17:38:11,719 - [DEBUG] - hm_pyhelper.miner_param - (miner_param.py).retry_get_region -- /opt/pktfwd-dependencies/hm_pyhelper/miner_param.py:(199) - No region override set (value = False), will retrieve from miner.
 packet-forwarder  2021-10-28 17:38:11,720 - [WARNING] - hm_pyhelper.miner_param - (api.py).__retry_internal -- /opt/pktfwd-dependencies/retry/api.py:(40) - [Errno 2] No such file or directory: '/var/pktfwd/region', retrying in 60 seconds...

The latest updates to diag, pktfwd have introduced a race condition / block on starting I think.

Diag waits for "lora module ready" - Miner waits for diag, packet forwarder waits for miner.

But the way we have it set now, the packet forwarder will not return ready, stopping diag, miner and packet forwarder from operating at al

Update startup script for dual frequency plans

Packet Forwarder Region Changes and Restart Logic

@hotspot-maker,

To operate correctly on the Helium network, a Hotspot needs to use the appropriate frequency settings (also known as a band plan) for its asserted location. These settings are ultimately stored on the blockchain and can change from time to time. It is important that you have both:

  • The most up-to-date band plans,
  • Automated logic to detect plan changes and restart the packet forwarder when necessary

We ask that you please check the latest frequency plans and adopt automatic
restart logic, as described further in this message.

Plan

The team plans to enact a changes to the blockchain which will require these
new plans and logic on November 11, 2022.

Most-Recent Band Plans

Band plans in the Helium network are identified by their name, such as us915 or as923_1b. The most up-to-date band plans are available in the various JSON configuration files at

https://github.com/helium/sx1302_hal/tree/helium/hotspot/packet_forwarder (helium/hotspot branch)

Please make sure that your firmware is updated such that it has the frequency information in each of these plans available at hand, even if the radio hardware in any particular Hotspot may not be able to support it.

WARNING: Each of these files contains example calibration hardware calibration data โ€“ please take care to keep any independent radio calibration data you have for your Hotspots intact and only adopt the frequency data in these files.

Automated Restart Logic

Helium will soon be adopting a band plan change for several parts of the world, most notably Malaysia and Australia. This change will be enacted by an update to a Helium blockchain variable, which is ultimately queryable via the miner. In order to ensure that your Hotspots respond to the change appropriately it is important that they regularly query the miner at some interval (once per minute) and restart the packet forwarder upon any detected change.

If you have adopted the general region detection scheme outlined in https://docs.helium.com/mine-hnt/full-hotspots/become-a-maker/docker-integration#omit-region_override then you should already be familiar with the regulatory region query procedure that your firmware makes at system startup to determine the correct configuration file to supply to the packet forwarder at its startup:

Example startup script for SX1302-based radios:

#!/bin/bash
set -o pipefail

# Query asserted region name from miner
while !REGULATORY_REGION=$( $MINERDIR/miner info region | sed -e s/^region_// | tr a-z A-Z | tr -d '\r\n'); do
    sleep 10
done

# Start up packet forwarder with correct band plan
lora_pkt_fwd_sx1302 -c global_conf.json.sx1250.$REGULATORY_REGION

We ask that you now add a supervisory script that restarts the packet forwarder whenever there is a detected change in the region name for the Hotspot.

Example new supervisory restart script:

#!/bin/bash
set -o pipefail

get_region() {
    $MINER_DIR/miner info region | tr a-z A-Z | tr -d '\r\n'
}

# Wait until gateway service comes online.
while ! REGULATORY_REGION="$( get_region )"; do
    sleep 1
done

# Keep looping as long as region doesn't change.
while :; do
    while ! NEW_REGION=$( get_region ) || [ "$NEW_REGION" = "$REGULATORY_REGION" ]; do
        sleep 60
    done
    REGULATORY_REGION="$NEW_REGION"
    # At this point, the region has changed, and we need to
    # restart the packet forwarder.
    RESTART_PACKET_FORWARDER # Implement this for your firmware
done
 

Lora Operational FALSE

Lora Opartional FALSE, and not responding on intern ip adres now , not syncing.

Worked for exactly 7 days and then down, the location is asserted right and the region is asserted. Any solving for this, because totally no response from helpdesk Nebra.

Schermafbeelding 2021-11-23 om 18 49 19

Improve failure checking

Currently we only try 5 times to start the concentrator and then say it's failed...

if(failTimes == 5):
with open("/var/pktfwd/diagnostics", 'w') as diagOut:
diagOut.write("false")

This doesn't work very well as sometimes it will fail more times than this, then work again, but the miner and diagnostics containers still get stuck because we do not check after 5 failures

X86_64 compatibility

We need the packet forwarder to be compatible with x86_64 so that we can start the FCC certification

Explore multi architecture containers

Acceptance criteria

  • 5g miner added to Balena fleet with pktfwd running without restart for at least 5 min
  • Validate that concentrator is working by running the QC scripts
  • Within pktfwd, retrieve chip_id from logs
  • Verify that the current test cases are working with USB concentrators
  • If needed, adjust the test script to work with USB concentrators
  • Test scripts need to work on X86_64

Join accept sending in wrong channel

Device tries to connect to hotspot within US915 freq channel but join accept is sending back by hotspot to the device in EU868.

Packet-forwarder conf seems fine.

Hotspot is located in EU.

  • What kind of mechanism behind is selecting the right frequency plan ?
  • Could moving the hotspot to the US might be fix it ?
[Logs]    [2022-5-23 1:17:43] [packet-forwarder] JSON down: {"txpk":{"codr":"4/5","data":"ILvNqFA9lCMJWaQRXf/xc28=","datr":"SF9BW125","freq":867.2999877929688,"imme":false,"ipol":true,"modu":"LORA","powe":20,"rfch":0,"size":17,"tmst":1784173964}}
[Logs]    [2022-5-23 1:17:43] [packet-forwarder] ERROR: Packet REJECTED, unsupported frequency - 867299987 (min:902000000,max:928000000)

console

GATEWAY_EUI is incorrect

I wanted to have the ability to remotely access my hotspots so I setup Balena with the RockPi 4B.

The problem I am having appears to be the packet-forwarder using 00:00:00:00:00:00:00:00 and 0 as GATEWAY_EUI.

2022-10-01 07:29:37.095 25 [info] <0.1646.0>@miner_mux_port:dispatch_port_logs:{118,13} [ gwmp-mux ] New packet forwarder client: 00:00:00:00:00:00:00:00, 172.17.0.5:43552
2022-10-01 07:29:37.098 25 [info] <0.1646.0>@miner_mux_port:dispatch_port_logs:{118,13} [ gwmp-mux ] Connecting to server 127.0.0.1:1681 on behalf of 00:00:00:00:00:00:00:00
2022-10-01 07:29:37.098 25 [info] <0.1646.0>@miner_mux_port:dispatch_port_logs:{118,13} [ gwmp-mux ] Connecting to server 127.0.0.1:1682 on behalf of 00:00:00:00:00:00:00:00
2022-10-01 07:29:37.099 25 [info] <0.1753.0>@miner_lora_light:handle_udp_packet:{350,5} PULL_DATA from 0 on 49329
2022-10-01 07:29:37.102 25 [info] <0.1637.0>@miner_gateway_port:dispatch_port_logs:{146,13} [ gateway-rs ] new packet forwarder client: 00:00:00:00:00:00:00:00, 127.0.0.1:47788

Bluetooth also appears to have issues and only works during initial boot/300 second sequence. I hold the button and nothing happens.

gateway-config Failed to register GATT advertisement: org.freedesktop.DBus.Error.NoReply: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.

I presume I have missed something - is there a copy of the original RockPi 4B firmware for balena so I can revert back (I really should have done this before hand)

Don't think reset_lgw.sh is used?

In the files we have two reset scripts:

Here, we sed the pin number for reset into the reset_lgw.sh script:
https://github.com/NebraLtd/hm-pktfwd/blob/master/files/configurePktFwd.py#L125-L128

But we never actually use that script, and instead are using reset-v2.sh:
https://github.com/NebraLtd/hm-pktfwd/blob/master/files/configurePktFwd.py#L130-L160

In the dockerfile we copy the reset_lgw.sh script over twice. Once here:
https://github.com/NebraLtd/hm-pktfwd/blob/master/Dockerfile#L93-L95

And the other time here:
https://github.com/NebraLtd/hm-pktfwd/blob/master/Dockerfile#L107-L109

I am pretty sure this is unnecessary, but need to test some more that it is not required for properly starting an sx1302/sx1303 based concentrator.

detect sx1303

we can detect the chip being sx1303 or sx1302, can be useful for some things in the future i guess

sx1302...

root@64709de465a7:/opt/iotloragateway/packet_forwarder# /opt/iotloragateway/packet_forwarder/sx1302/util_chip_id/chip_id -d /dev/spidev0.0
CoreCell reset through GPIO17...
Opening SPI communication interface
Note: chip version is 0x10 (v1.0)
INFO: using legacy timestamp
ARB: dual demodulation disabled for all SF

INFO: concentrator EUI: 0x0016c001ff1a08f0

Closing SPI communication interface
CoreCell reset through GPIO17...

Sx1302 not working

Sx1302 / sx1303 not working with current packet forwarder. Need to investigate why

CalledProcessError: Command '['/opt/sx1302/chip_id', '-d', '/dev/spidev32766.0']' returned non-zero exit status 1.

Sentry Issue: HM-PKTFWD-F

CalledProcessError: Command '['/opt/sx1302/chip_id', '-d', '/dev/spidev32766.0']' returned non-zero exit status 1.
  File "/opt/pktfwd/utils.py", line 70, in is_concentrator_sx1302
    subprocess.run(util_chip_id_cmd, capture_output=True,
  File "subprocess.py", line 524, in run
    raise CalledProcessError(retcode, process.args,

SX1301 detected. util_chip_id script exited with error.

add check for spi bus config.txt line

if you do not enable the correct SPI bus, the lora concentrator fails to start with the error message...

ERROR: [main] failed to start the concentrator

however this is not really particularly helpful as an error message in this instance.

Perhaps there should be a check to see if the SPI bus defined in the variant_definitions.py file is actually enabled.

We can do this by searching for it in /dev using something like:

ls /dev | grep -i spi_bus

where spi_bus is the SPIBUS that is declared in variant_definitions.py

str() function on a string?

When fixing some stuff in light-hotspot-software, I came across this:

spi_bus = variant_variables['SPIBUS']
print("Hardware Variant %s Detected" % variant)
print("SPI: %s" % reset_pin)
print("RESET: %s" % str(spi_bus))

The reset and spi_bus were back to front.

I have corrected it this:

spi_bus = variant_variables['SPIBUS']
print("Hardware Variant %s Detected" % variant)
print("RESET: %s" % str(reset_pin))
print("SPI: %s" % spi_bus)

However due to my limited knowledge of code, I just wanted to get a sense check @vpetersson ... basically, I thought the str(spi_bus) was somewhat pointless as it is already a string? I am guessing the str() function was meant to be used for the reset_pin variable as that is a number?

AS923_1 asserted cause lora operational false

I got two new nebra indoor miner 2021/9/27. I power on the first one, and local diagnostic showed all ok. However the local diagnostic showed lora operational error after the region asserted to AS923_1.
I power on the another one. The local diagnostic showed all ok in the beginning, and then the lora operational became false, after AS923_1 was asserted to region.
Please check this issue. my ticket 282366

Rssi too strong compared to other hotspots

At least for Europe, RSSI reported by some Nebra hotspot is really high compared to other nearest hotspot. As a consequence, the Nebra hotspot get Join Accept, ack and donwlink messages to process. This is applicable to hotspot used with outdoor antennas.
As an example, I've seen -80dBm > -90dBm over 13.8km. Free space path loss for 13.8km is 100dBm confirming the Nebra Rssi to be valid for 14dBm, but the problem it is really higher than the others.

Other hotspots are reporting for the same mesage:

  • 7km / -118dBm (outdoor rak DiY)
  • 8km / -115dBm (outdoor Rak hotspot)
  • 8km / -107dBm (outdoor Rak hotspot)
    Compared to Nebra
  • 13,8km / -89dBm

As a consequence, since this Nebra is up, there is a real difficulty for devices in the city to join the network and receiving Ack.

Issues with Australian miners

Since update 2021.09.14.0 Nebra Miner users in Australia have been experiencing a lot of issues. Many of them have not received a successful witness / appearing offline since the update. This is the second time in two weeks the miners have been offline.

Also, the Frequency is showing as 917.4 MHz instead of 915 MHz.
Screenshot 2021-09-16 at 10 02 04

sx1302 fixes?

We need to determine the reason for the sx1302 fixes and document it.

Additionally investigate if there is a better / more easily maintainable way of handling them.

Packet forwarder failed to start concentrator

Hi I have a problem with the concentrator is it possible that I missed something if I have the wrong variables in balena.cloud?
Or it's a problem in lora_templates_sx1302 / EU-global_conf.json.
My original system was probably damaged due to a poor Wi-Fi network. I have nebra indoor miner NEBHNT-IN1 for EU868.
This is my balena.cloud variables
REGION_OVERRIDE not defined EU868 packet-forwarder
VARIANT not defined NEBHNT-IN1 diagnostics
VARIANT not defined NEBHNT-IN1 gateway-config
VARIANT not defined NEBHNT-IN1 packet-forwarder
Thank you for any help.

KeyError: 'region_eu868' Packet Forwarder crashing

10.11.21 15:24:59 (+0100) packet-forwarder Starting
10.11.21 15:25:01 (+0100) packet-forwarder SX1301
10.11.21 15:25:01 (+0100) packet-forwarder Frequency region_eu868
10.11.21 15:25:02 (+0100) packet-forwarder Traceback (most recent call last):
10.11.21 15:25:02 (+0100) packet-forwarder File "configurePktFwd.py", line 151, in
10.11.21 15:25:02 (+0100) packet-forwarder writeRegionConfSx1301(regionID)
10.11.21 15:25:02 (+0100) packet-forwarder File "configurePktFwd.py", line 99, in writeRegionConfSx1301
10.11.21 15:25:02 (+0100) packet-forwarder regionconfFile = "/opt/iotloragateway/packet_forwarder/sx1301/lora_templates_sx1301/"+regionList[regionId]
10.11.21 15:25:02 (+0100) packet-forwarder KeyError: 'region_eu868'

Happening on https://dashboard.balena-cloud.com/devices/33e2f8d0d955afe3f46c7d6ae6a3bd9c/summary and
https://dashboard.balena-cloud.com/devices/cedf46b90d401a31fc86a7eea99d874a/summary

CalledProcessError: Command '['/opt/sx1302/chip_id', '-d', '/dev/spidev1.2']' returned non-zero exit status 1.

Sentry Issue: HM-PKTFWD-4

CalledProcessError: Command '['/opt/sx1302/chip_id', '-d', '/dev/spidev1.2']' returned non-zero exit status 1.
  File "/opt/pktfwd/utils.py", line 70, in is_concentrator_sx1302
    subprocess.run(util_chip_id_cmd, capture_output=True,
  File "subprocess.py", line 524, in run
    raise CalledProcessError(retcode, process.args,

SX1301 detected. util_chip_id script exited with error.

Packet Forwarder crashing out in AS923 region.

The latest update of the miner (GA 29th of May) introduced the new regions of AS923_1, AS923_2, AS923_3 and AS923_4

As no warning was given of this change the packet forwarder doesn't have a matching index for these variables (Nor I think a frequency plan for AS923_3 & AS923_4).

These new plans need to be added, then updated on the index.

sx1303 support

ensure sx1303 works correctly with sx1302 config files

Refactor and add RockPi support

Notes

  • Move logic to hm-pyhelper, where appropriate.
  • Need consistency in how repos are structured.
  • Why are we using sed?
  • Can potentially be rewritten to bash.

Acceptance criteria

  • Use python logging instead of print statements
  • No camelCasing
  • Same code should work for RaspberryPi and RockPi

Spike: feature parity with helium forks of 1301 and 1302 pktfwd

The helium forks of pktfwd seem to have some changes. Most of them are small fixes but we saw a few that change buffer size to accommodate larger payloads.
it might be worthwhile to investigate those changes and see if we need a backport merge to our repo. Helium and our repo are forked from same upstream LoraNet repo. Merge shouldn't be a big issue if required.

KeyError: 'region_us915'

Sentry Issue: HM-PKTFWD-7

KeyError: 'region_us915'
  File "__main__.py", line 100, in start
    pktfwd_app.start()
  File "/opt/pktfwd/pktfwd_app.py", line 45, in start
    update_global_conf(is_sx1302, self.root_dir,
  File "/opt/pktfwd/utils.py", line 114, in update_global_conf
    replace_sx1301_global_conf_with_regional(root_dir,
  File "/opt/pktfwd/utils.py", line 128, in replace_sx1301_global_conf_with_regional
    get_region_filename(region))
  File "/opt/pktfwd/utils.py", line 99, in get_region_filename
    return REGION_CONFIG_FILENAMES[region]

__main__ failed for unknown reason

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.