text:
# lifxlan

**lifxlan** is a Python 3 module for locally controlling LIFX devices (such as lightbulbs) over a LAN. It implements the [LIFX LAN Protocol](https://lan.developer.lifx.com/) specification. Supports white, color, multizone (LIFX Z, LIFX Beam), infrared (LIFX+), and chain (LIFX Tile) capabilities. Also supports group-based control of arbitrary sets of lights. Supports Unicode characters in names, groups, and locations.

## How to Install

To get the latest stable release:

`sudo pip install lifxlan`

However, to be guaranteed to get the most recent features and fixes you can install from source with:

`sudo python setup.py install`

## Run

See the `examples` folder for example scripts that use **lifxlan**.

To be as generic as possible, the examples use automatic device discovery to find individual bulbs, which causes a short but noticeable delay. To avoid device discovery, you can either instantiate Light objects directly using their MAC address and IP address (which you can learn by running `examples/hello_world.py`), or you can use the broadcast methods provided in the LifxLAN API. In the examples folder, `broadcast_on.py`, `broadcast_off.py`, and `broadcast_color.py` will allow you to send commands to all lights quickly from the command line without doing device discovery.

## Overview

You can do several things with this library:

- Control LIFX devices using the package's high-level API (see the `examples` folder and the following API sections).
- Build your own high-level API on top of the low-level networking messages.
- Build virtual LIFX devices in software (think adapters for Philips Hue bulbs, etc).

#### High-Level API:

- **lifxlan.py** - Provides the LifxLAN API, and low-level API for sending broadcast LIFX packets to the LAN.
- **device.py** - Provides the Device API, and low-level API for sending unicast LIFX packets to a Device.
- **light.py** - Provides the Light API. Subclass of Device.
- **multizonelight.py** - Provides the MultiZoneLight API. Subclass of Light.
- **tilechain.py** - Provides the TileChain API. Subclass of Light.
- **group.py** - Provides the Group API. Allows you to perform synchronized actions on groups of devices.

##### LifxLAN API

You can create a LifxLAN object to represent the local network:

```
lan = LifxLAN()
lan = LifxLAN(num_lights)   #this will make discovery go faster if all lights are responsive
```

LifxLAN objects have the following methods:

```
# power can be "on"/"off", True/False, 0/1, or 0/65535
# color is a list of HSBK values: [hue (0-65535), saturation (0-65535), brightness (0-65535), Kelvin (2500-9000)]
# duration is the transition time in milliseconds
# rapid is True/False. If True, don't wait for successful confirmation, just send multiple packets and move on
# NOTE: rapid is meant for super-fast light shows with lots of changes. You should't need it for normal use.
# arguments in [square brackets] are optional
# name is the string label for the light, such as "Right Lamp"
# names is a list of name strings, such as ["Left Lamp", "Right Lamp"]
# group is a string label for a group, such as "Living Room"
# location is the string label for a location, such as "My Home"

get_lights()                                                                                # returns list of Light objects
get_color_lights()                                                                           # returns list of Light objects that support color functionality
get_infrared_lights()                                                                        # returns list of Light objects that support infrared functionality
get_multizone_lights()                                                                       # returns list of MultiZoneLight objects that support multizone functionality
get_tilechain_lights()                                                                       # returns a list of TileChain objects that support chain functionality
get_device_by_name(name)                                                                     # returns a Device object (instantiated as the most specific Device subclass possible, such as MultiZoneLight)
get_devices_by_name(names)                                                                   # returns a Group object
get_devices_by_group(group)                                                                  # returns a Group object
get_devices_by_location(location)                                                            # returns a Group object
set_power_all_lights(power, [duration], [rapid])                                             # set power for all lights on LAN
set_color_all_lights(color, [duration], [rapid])                                             # set color for all lights on LAN
set_waveform_all_lights(is_transient, color, period, cycles, duty_cycle, waveform, [rapid])  # see the Light API for more details
get_power_all_lights()                                                                       # returns dict of Light, power pairs
get_color_all_lights()                                                                       # returns dict of Light, color pairs
```

##### Device API

In keeping with the LIFX protocol, all lights are devices, and so support the following methods:

```
# label is a string, 32 char max
# power can be "on"/"off", True/False, 0/1, or 0/65535
# rapid is True/False. If True, don't wait for successful confirmation, just send multiple packets and move on
# NOTE: rapid is meant for super-fast light shows with lots of changes. You should't need it for normal use.
# arguments in [square brackets] are optional

set_label(label)
set_power(power, [rapid])
get_mac_addr()
get_ip_addr()
get_service()                       # returns int, 1 = UDP
get_port()
get_label()
get_power()                         # returns 0 for off, 65535 for on
get_host_firmware_tuple()           # returns (build_timestamp (in nanoseconds), version)
get_host_firmware_build_timestamp()
get_host_firmware_version()
get_wifi_info_tuple()               # returns (wifi_signal_mw, wifi_tx_bytes, wifi_rx_bytes)
get_wifi_signal_mw()
get_wifi_tx_bytes()
get_wifi_rx_bytes()
get_wifi_firmware_tuple()           # returns (build_timestamp (in nanoseconds), version)
get_wifi_firmware_build_timestamp()
get_wifi_firmware_version()
get_version_tuple()                 # returns (vendor, product, version)
get_location()                      # Returns location id (bytearray length 16)
get_location_tuple()                # Returns a tuple of location(bytearray lenght 16), location_label(string), and location_updated_at(unsigned 64 bit epoch timestamp)
get_location_label()                # Returns location_label string
get_location_updated_at             # Returns location_updated_at unsigned 64 bit int -> epoch timestamp
get_group()                         # Returns group id (bytearray length 16)
get_group_tuple()                   # Returns a tuple of group(bytearray lenght 16), group_label(string), and group_updated_at(unsigned 64 bit epoch timestamp)
get_group_label()                   # Returns group_label(string)
get_group_updated_at                # Returns group_updated_at unsigned 64 bit int -> epoch timestamp
get_vendor()
get_product()
get_version()
get_info_tuple()                    # returns (time (current timestamp in ns), uptime (in ns), downtime (in ns, +/- 5 seconds))
get_time()
get_uptime()
get_downtime()
is_light()                          # returns True if device is some kind of light product
supports_color()                    # returns True if product features include color
supports_temperature()              # returns True if product features include white color temperature
supports_multizone()                # returns True if product features include multizone functionality
supports_infrared()                 # returns True if product features include infrared functionality
```

##### Light API

You can get Light objects automatically though LAN-based discovery (takes a few seconds), or by creating Light objects using a known MAC address and IP address:

```
lights = lan.get_lights()                              # Option 1: Discovery
light = Light("12:34:56:78:9a:bc", "<IP_ADDRESS>")     # Option 2: Direct
```

The Light API provides everything in the Device API, as well as:

```
# arguments in [square brackets] are optional
# power can be "on"/"off", True/False, 0/1, or 0/65535
# color is a HSBK list of values: [hue (0-65535), saturation (0-65535), brightness (0-65535), Kelvin (2500-9000)]
# duration is the transition time in milliseconds
# rapid is True/False. If True, don't wait for successful confirmation, just send multiple packets and move on
# is_transient is 1/0. If 1, return to the original color after the specified number of cycles. If 0, set light to specified color
# period is the length of one cycle in milliseconds
# cycles is the number of times to repeat the waveform
# duty_cycle is an integer between -32768 and 32767. Its effect is most obvious with the Pulse waveform
#     set duty_cycle to 0 to spend an equal amount of time on the original color and the new color
#     set duty_cycle to positive to spend more time on the original color
#     set duty_cycle to negative to spend more time on the new color
# waveform can be 0 = Saw, 1 = Sine, 2 = HalfSine, 3 = Triangle, 4 = Pulse (strobe)
# infrared_brightness (0-65535) - is the maximum infrared brightness when the lamp automatically turns on infrared (0 = off)

# NOTE: rapid is meant for super-fast light shows with lots of changes. You should't need it for normal use.

set_power(power, [duration], [rapid])
set_color(color, [duration], [rapid])
set_waveform(is_transient, color, period, cycles, duty_cycle, waveform)
get_power()                                                                 # returns 0 or 65535
get_color()                                                                 # returns color (HSBK list)
get_infrared()                                                              # returns infrared brightness (0 to 65535), or None if infrared is not supported
set_infrared(infrared_brightness)
```

The Light API also provides macros for basic colors, like RED, BLUE, GREEN, etc. Setting colors is as easy as `mybulb.set_color(BLUE)`. See light.py for complete list of color macros.

Finally, you can set parts of the color individually using the following four methods. However, the bulbs must receive all four values in each SetColor message. That means that using one of the following methods is always slower than using set_color(color) above because it will have to call get_color() first to get the other three values.

```
set_hue(hue, [duration], [rapid])                  # hue in range [0-65535]
set_brightness(brightness, [duration], [rapid])    # brightness in range [0-65535]
set_saturation(saturation, [duration], [rapid])    # saturation in range [0-65535]
set_colortemp(kelvin, [duration], [rapid])         # kelvin in range [2500-9000]
```

##### MultiZoneLight API

Lights with MultiZone capability, such as the LIFX Z, have all the same methods as the Light API, and also add the following:

```
# start and end refer to zone indices (inclusive).
# duration is the transition time in milliseconds
# rapid is True/False. True means there is no guarantee that the bulb will receive your message.
# apply is 1/0. If 0, queue up the change until a packet with apply=1 comes by, then apply all queued changes.
# effect_type is 0 for None, 1 for Move

get_color_zones([start], [end])                                    # returns a list of [H,S,V,K] colors, one for each zone. Length of the list is the number of zones.
set_zone_color(start, end, color, [duration], [rapid], [apply])    # indices are inclusive and zero-indexed
set_zone_colors(colors, [duration], [rapid])                       # colors is a list of [H,S,V,K] colors, which will get applied to the zones in order. This makes it possible to restore the original colors easily after a display.
get_multizone_effect()                                             # returns current firmware effect status
set_multizone_effect([effect_type], [speed], [duration], [instanceid], [parameters], [rapid]) # starts the firmware effect sequence
```

The LIFX Z can be instantiated as either a Light or MultiZoneLight object, but to use the MultiZone API you'll need to instantiate it as a MultiZoneLight. Just like with more generic Light objects, you can instantiate a MultiZoneLight directly with `light = MultiZoneLight("12:34:56:78:9a:bc", "<IP_ADDRESS>")`. You can also get a list of all MultiZone lights using `lights = lan.get_multizone_lights()`, where lan is a LifxLAN object.

##### TileChain API

TileChain lights, such as the LIFX Tile, have all the same methods as the Light API, and also add the following:

```
# refresh_cache is a binary value. If True, send the query directly to the light to get the answer, and update the locally stored information (slower). If False, return the locally stored answer from a previous query (faster). Should almost always be False, unless the configuration of the Tiles is expected to change while the program is running (an unusual concern for most programs).
# tile_count is the number of tiles on which to replicate the command, starting from the start_index tile.
# x, y, and width will probably not be used. They allow the user to specify a rectangle of LEDs on the specified tile. The (x, y) coordinate gives the starting LED, and the width gives the width of the desired rectangle. The default values of these ((0, 0) and 8) specify the whole tile, and will probably not need to be changed.
# colors is a list of 64 HSVK tuples.
# tilechain_colors is a list of tile_count x 64 HSVK tuples, used for getting and setting the entire TileChain's colors at once.
# hsvk_matrix is a 2D list of HSVK color tuples with canvas_dimensions rows and cols. The canvas_dimensions will depend on the configuration of the tiles. The canvas can be thought of as the rectangular bounding box around the entire TileChain, where each pixel is an LED.
# effect_type is 0 for None, 2 for Morph and 3 for Flame. 1 is Reserved.

get_tile_info([refresh_cache])                                  # returns a list of Tile objects
get_tile_count([refresh_cache])                                 # returns the number of Tiles in the TileChain light
get_tile_colors(start_index, [tile_count], [x], [y], [width])   # returns colors for the specified tile(s).
set_tile_colors(start_index, colors, [duration], [tile_count], [x], [y], [width], [rapid]) # sets the colors on the specified tile(s). For tile_count > 1, the colors will be duplicated.
get_tilechain_colors()                                          # returns tilechain_colors
set_tilechain_colors(tilechain_colors, [duration], [rapid])     # sets all the colors on the whole TileChain
project_matrix(hsvk_matrix, [duration], [rapid])                # projects the given matrix of colors onto the TileChain.
get_canvas_dimensions([refresh_cache])                          # returns (x, y), representing the rows and columns of the bounding box around the entire TileChain, where each element is an individual LED position.
get_tile_effect()                                               # returns current firmware effect status
set_tile_effect([effect_type], [speed], [duration], [palette], [instanceid], [parameters], [rapid]) # starts the firmware effect sequence
```

Here are some other available methods that you are much less likely to use:

```
# x and y below are in units of tile length, not LED rows/cols. In other words, the x and y below are not the same as the x and y above.

recenter_coordinates()                  # This will permanently shift all the tile coordinates so that they are centered around a tile at (0, 0). Sometimes the app will result in a particular axis being off (e.g., the origin tile is (0, -0.5), so all the tile coordinates are shifted by -0.5). This method isn't necessary for any functionality, but makes the tile_info a little more human-readable.
set_tile_coordinates(tile_index, x, y)  # Permanently sets the specified tile's coordinates to x and y (in tile length units) relative to the central tile. Tile coordinates are generally set through the LIFX app, and it is unlikely you will need to ever use this method unless you're doing something pretty weird. (If so, drop me a line!)
get_tile_map([refresh_cache])           # Returns a 2D list with canvas_dimensions rows and cols where each element contains either a (tile_index, color_index) tuple or 0. This maps a pixel on the canvas to the tile number and LED number on that tile that the pixel corresponds to, or 0 if there is no tile in that location.
```

A LIFX Tile light can be instantiated as either a Light or TileChain object, but to use the TileChain API you'll need to instantiate it as a TileChain. Just like with more generic Light objects, you can instantiate a TileChain directly with `light = TileChain("12:34:56:78:9a:bc", "<IP_ADDRESS>")`. You can also get a list of all tilechain lights using `lights = lan.get_tilechain_lights()`, where lan is a LifxLAN object.

##### Group API

A Group is a collection of devices. Under the covers, a Group is just a list of device objects (like Devices, Lights, MultiZoneLights) and a set of functions that send multi-threaded commands to the applicable devices in the group. The multi-threading allows changes to be made more or less simultaneously. At the very least, it is certainly faster than if you looped through each individual light one at a time. You can get a Group by group, location, or device names via the LifxLAN API. However, you can also instantiate a Group with any arbitrary list of device objects. Here are some ways to create groups:

```
# The following methods use discovery
lan = LifxLAN()
g = lan.get_devices_by_name(["Left Lamp", "Right Lamp"])
g = lan.get_devices_by_group("Living Room")
g = lan.get_devices_by_location("My Home")

# This method is fastest
right = Light("12:34:56:78:9a:bc", "<IP_ADDRESS>")
left = Light("cb:a9:87:65:43:21", "<IP_ADDRESS>")
g = Group([right, left])
```

Almost all of the Group API methods are commands. Commands will only be sent to the devices in the group that support that capability. If you want to get state information from the devices, you will need to access the list of devices and call their get methods directly.

```
# device_object is a Device or any of its subclasses like Light and MultiZoneLight.
# device_name is a string name of a device, like "Right Lamp"
# power can be "on"/"off", True/False, 0/1, or 0/65535
# color is a HSBK list of values: [hue (0-65535), saturation (0-65535), brightness (0-65535), Kelvin (2500-9000)]
# infrared_brightness is an integer between 0 and 65535.
# duration is the transition time in milliseconds
# rapid is True/False. If True, don't wait for successful confirmation, just send multiple packets and move on
# start and end refer to zone indices (inclusive).
# apply is 1/0. If 0, queue up the change until a packet with apply=1 comes by, then apply all queued changes.

add_device(device_object)
remove_device(device_object)
remove_device_by_name(device_name)
get_device_list()
set_power(power, [duration], [rapid])
set_color(color, [duration], [rapid])
set_hue(hue, [duration], [rapid])
set_brightness(brightness, [duration], [rapid])
set_saturation(saturation, [duration], [rapid])
set_colortemp(kelvin, [duration], [rapid])
set_infrared(infrared_brightness)
set_zone_color(start, end, color, [duration], [rapid], [apply])
set_zone_colors(colors, [duration], [rapid])
```

#### LIFX LAN Protocol Implementation:

The LIFX LAN protocol specification is officially documented [here](https://lan.developer.lifx.com/). In lifxlan, you can see the underlying stream of packets being sent and received at any time by initializing the LifxLAN object with the verbose flag set: `lifx = LifxLAN(verbose = True)`. (See `examples/verbose_lan.py`.) You can also set the verbose flag if creating a Light or MultiZoneLight object directly.

The files that deal with LIFX packet construction and representation are:

- **message.py** - Defines the message fields and the basic packet structure.
- **msgtypes.py** - Provides subclasses for each LIFX message type, along with their payload constructors.
- **unpack.py** - Creates a LIFX message object from a string of binary data (crucial for receiving messages).

Happy hacking!

repository: mclarkk/lifxlan

repo_name: mclarkk/lifxlan


text:
+++
showonlyimage = true
draft = false
image = "img/texas_range_love_field.jpg"
date = "2020-06-04T09:00:00-05:00"
title = "One Riot, One Ranger—Dallas, TX, USA"
photo_credits = "Juan Figueroa/The Dallas Morning News"
photo_source_url = "https://www.dallasnews.com/arts-entertainment/visual-arts/2020/06/03/the-statue-of-the-texas-ranger-at-love-field-may-be-coming-down/"
categories = [ "colonizers", "racists" ]
tags = ["municipal-action"]
subjects = ["Jay Banks"]
weight = 1
+++

The statue depicting the Texas Ranger Captain Jay Banks[^1], titled "One Riot, One Ranger" has been removed from Dallas Love Field Airport by the City of Dallas[^2].

<!--more-->

The city was prompted to remove the statue after receiving an excerpt from a book that will be published soon about the Texas Rangers, titled "Cult of Glory"[^3].  It was donated to the city in 1963, and has been now placed in storage.

#### References

[^1]: [Texas Ranger Statue Removed at Dallas Love Field](https://dfw.cbslocal.com/2020/06/04/texas-ranger-statue-removed-dallas-love-field/)

[^2]: [Texas Ranger statue at Love Field removed over concerns about the depicted lawman's racist history](https://www.dallasnews.com/arts-entertainment/visual-arts/2020/06/03/the-statue-of-the-texas-ranger-at-love-field-may-be-coming-down/)

[^3]: [The Texas Rangers didn't invent police brutality, says the author of a new book, 'they perfected it'](https://www.dallasnews.com/arts-entertainment/books/2020/06/03/the-texas-rangers-didnt-invent-police-brutality-says-the-author-of-a-new-book-they-perfected-it/)

license: MIT

repository: Gorcenski/whentheycamedown

branch_name: refs/heads/trunk

extension: md

gha_language: CSS

gha_license_id: NOASSERTION

license_type: permissive

repo_name: Gorcenski/whentheycamedown


text:
---
layout: page
title: About
---

I am {{ site.author.name }}, a *{{ site.author.trade }}* by trade. I also teach kids how to write code, primarily in `java` and `python`

{{ site.description }}

* Call or Whatsapp at [{{site.author.phone}}](tel:{{site.author.phone}})
* Send me an email at [{{ site.author.email }}](mailto:{{site.author.email}})
* Visit my Professional Profile here

## Submit a Question

If you have a programming question, suggestions or feedback then submit it through this google form - I will try my best to get back to you.

Thanks for visiting {{ site.title }}!

repository: banutsav/himucode

branch_name: refs/heads/master

repo_name: banutsav/himucode


text:
data.rfc5322\_header\_checks
==========================

NOTICE: this plugin is deprecated. Use data.headers instead.

This plugin enforces RFC 5322 Section 3.6 which states that:

All messages MUST have a 'Date' and 'From' header and a message may not contain
more than one 'Date', 'From', 'Sender', 'Reply-To', 'To', 'Cc', 'Bcc',
'Message-Id', 'In-Reply-To', 'References' or 'Subject' header.

Any message that does not meet these requirements will be rejected.

repository: haraka/Haraka

gha_language: JavaScript

gha_license_id: MIT

repo_name: haraka/Haraka


text:
# PostHog PHP

Please see the main [PostHog docs](https://posthog.com/docs).

Specifically, the [PHP integration](https://posthog.com/docs/integrations/php-integration) details.

repository: shamakhan/posthog-php

repo_name: shamakhan/posthog-php


text:
# DroidBruter
DroidBruter is an Android Phone PIN Bruteforcer Tool if you forgot your phone's PIN Code.

## Disclaimer
Please ask for permission first before attempting to bruteforce one of your friend or family's android phones.

I am not responsible for any damage or trouble caused by this script.

## Script Features
* Device Detection
   * Waits every 5 seconds to reconnect the device when disconnected
* 3-32 PIN Support
* Optimized PINs
   * Optimized PINs for 3, 4, 5, 6 digit PINs
* Editable PIN Cooldown
   * Puts 4 PINs (maxatmp) every 600 seconds (10 mins | maxatmpcd)

## Available Commands

```
  help                            Shows all DroidBruter commands
  start [<-opt>]                  Starts bruteforcing the phone with settings
  exit                            Stops the server and exits DroidBruter
  pinlength <length>              Changes the pin length
  maxatmp <int>                   Changes the max attempts for placing PINs
  maxatmpcd <int>                 Sets the max attempts cooldown
  settings                        Shows current settings
  defpin <int>                    Changes starting PIN
  refresh                         Refreshes the DroidBruter Bruteforce Console
  toggleenter <-true | -false>    Presses enter after placing PIN
```
## Changing Pins
To change pins you can type ``pinlength 6`` in the DroidBruter command line to change pins to 6.

Type ``settings`` in the command line to confirm

## DroidBruter Screenshots
![DroidBruter Screen](https://user-images.githubusercontent.com/53323309/126936418-ac0fa43f-8edd-4f68-ae4c-b045e8949140.png)
![DroidBruter Help](https://user-images.githubusercontent.com/53323309/126936476-ff27c801-9ac6-4432-9bcd-efb685982cd3.png)

branch_name: refs/heads/main


text:
# InteractiveMusicInstallation

Created by Omid Ettehadi on 6/Nov/2018 For OCAD University - Creation & Computation - DIGF-6037

Project Description: This is an Interactive Musical Installation, where the device requests the audience to engage in the experience by playing a beat sequence when they get close to the object. There are three sets of instruments each with three notes. Three people can press the pads to create a song together.

Includes:
- P5.JS
- Arduino


text:
Simulation of vessel length distributions: Code from Link et al., 2018
================

Description
-----------

This repository contains the code for the simulations from Link et al., 2018, *Maximum likelihood estimation of xylem vessel length distributions*. Link: https://doi.org/10.1016/j.jtbi.2018.07.036

The scripts contained in this repository were used to generate and analyze the Monte Carlo samples of vessel length distributions discussed in said paper, and we refer to the full text for full documentation.

Contents and structure
----------------------

The repository is structured as follows:

``` text
/         basic scripts:
          01_sampling_settings.R  -- creates and exports the table that stores the settings
                                     used for the random samples
          02_model_fitting.R      -- performs random sampling, model fitting and evaluation
          03_figures_and_output.R -- creates the figures and tables for the publication
/figures  -- figures with model results
/output   -- model output and tables used in the paper
/R        -- 01_VL_distributions.R            -- utility functions for vessel length analyses
                                                 (identical to S3: VLscripts.R, renamed for clarity)
             02_VL_samples.R                  -- functions for the generation of random samples of
                                                 vessel lengths
             03_VL_subsamples.R               -- functions for the generation of subsamples of
                                                 vessel lengths based on the output of the scripts
                                                 in "R/02_VL_samples.R"
             04_VL_models.R                   -- code that automates model fitting on vessel length
                                                 data based on the desired settings
             05_VL_accuracy.R                 -- utility functions for the analysis of the accuracy
                                                 of vessel length predictions
             gg_publication_themes_20180305.R -- settings for graphics
/settings -- table with the settings defined in "01_sampling_settings.R"
```

The following figure shows a flowchart of the work flow of the project:

![flowchart](figures/flowchart.png)


text:
---
layout: news_item
title: 'Frida 15.1.18 Released'
date: 2022-05-04 19:43:52 +0200
author: oleavr
version: 15.1.18
categories: [release]
---

Lots of improvements all over the place this time. Many stability improvements.

I have continued improving our CI and build system infrastructure. QNX and MIPS
support are back from the dead, after long-standing regressions. These went
unnoticed due to lack of CI coverage. We now have CI in place to ensure that
won't happen again.

Do check out the changelog below for a full overview of what's new.

Enjoy!

### Changelog

- gadget: Fix deadlock when Gadget is blocking the dynamic linker with its
  internal lock(s) held while waiting for resume(). In that case we are
  processing the JS MainContext while blocking, with network I/O handled by the
  Gadget thread. Because Stalker may interact with the dynamic linker during its
  class_init(), we must ensure that it happens from the JS thread and not the
  network I/O thread.
- exit-monitor: Fix deadlock when a fork() goes unnoticed.
- darwin: Skip pseudo-signing when running on Corellium.
- darwin: Fix compatibility with older iOS SDKs.
- darwin-backtracer: Fix loop variable wrap-around.
- darwin-mapper: Fix footprint budgeting w/ chained fixups.
- linux: Fix the Process.modify_thread() wait logic.
- linux: Fully resolve libc on modern glibc systems.
- linux: Remove the Linjector cleanup delay.
- ios: Add config.mk option for building without jailbreak support code, for
  compatibility with e.g. TestFlight.
- ios: Eliminate dependency on external Mach VM header.
- android: Fix unw_getcontext() on Android/x86, which resulted in stack
  corruption during e.g. Thread.backtrace().
- freebsd: Add BSDmakefile for convenience.
- freebsd: Fix gum_clear_cache() reliability.
- freebsd: Improve the program path query API.
- freebsd: Try a bit harder when MAP_32BIT fails.
- mips: Fix long-standing regressions that went unnoticed due to lack of CI.
- qnx: Fix long-standing regressions that went unnoticed due to lack of CI. Also
  improve the QNX backend while at it.
- posix: Use posix_madvise() if madvise() is unavailable.
- stalker: Detect thread exit implementation on glibc, Android, and FreeBSD.
- stalker: Fix Linux clone() support in the x86 backend.
- stalker: Fix backpatching of JECXZ/JRCXZ x86 instructions.
- stalker: Fix two *pc* vs *code* mixups in the x86 backend.
- stalker: Optimize Linux syscall logic in the x86 backend.
- stalker: Move unwind support behind an API.
- stalker: Simplify and fix the x86 unwind Interceptor logic.
- stalker: Implement unwind hooking in the arm64 backend. Thanks [@s1341][]!
- stalker: Add backpatch query support.
- stalker: Add support for recompiling blocks.
- process: Add resolve_module_pointer().
- elf-module: Improve the DT_SYMTAB entry count detection.
- elf-module: Skip symbols with a dangling name reference.
- symbolutil-libdwarf: Add support for DWARF v5.
- libdwarf: Backport upstream fix for handling of DW_FORM_line_strp.
- dbghelp-backtracer: Improve reliability on 32-bit x86.
- arm-relocator: Simplify PC-relative *LDR* handling.
- arm-writer: Add call_reg_with_arguments*().
- arm-writer: Handle put_call*() w/ more than four args.
- thumb-writer: Handle put_call*() stack alignment.
- arm64-writer: Optimize *LDR reg, #0*.
- x86-relocator: Add *input_pc* to support offline use.
- x86-relocator: Fix PC vs output mixup in RIP-relative fast-path.
- x86-relocator: Improve the RIP offset fixup logic.
- bounds-checker: Fall back to the matching heap API.
- gumjs: Fix CModule memory allocation logic.
- gumjs: Fix CModule runtime with internal TinyCC.
- gumjs: Lower build-time Python requirement to 3.7.
- heap-api: Improve libc detection on non-Windows OSes.
- heap-api: Include static MSVC CRT APIs in the list.
- gum: Improve Meson build system to support MSVC.
- gum: Improve Gum vapis to expose more APIs.
- core: Fix build failure with some locales by switching off localization when
  invoking tools from modulate.py.
- python: Fix stability issue caused by incorrect refcounting in
  get_max_argument_count().
- python: Fix get_index_url_from_pip(). Thanks [@X5tar][]!
- python: Fix index URL retrieval on Python < 3.6. Thanks [@serfend][]!
- node: Publish prebuilds for Electron 18 instead of 16.
- ci: Add Linux/MIPS, FreeBSD/x86_64, FreeBSD/arm64, and QNX/armeabi. For Gum,
  also add Windows/x86_64, macOS/x86_64, Linux/x86, Linux/x86_64, iOS/arm64,
  Android/x86, Android/arm, and Android/arm64.

[@s1341]: https://github.com/s1341
[@X5tar]: https://github.com/X5tar
[@serfend]: https://github.com/serfend

repository: frida/frida-website

extension: markdown

repo_name: frida/frida-website


text:
---
id: 63
title: Loads of new music
date: 2009-06-04T03:30:44+00:00
author: happyseizure
layout: post
guid: http://happyseizure.wordpress.com/?p=63
permalink: /2009/06/loads-of-new-music/
categories:
  - Miscellaneous
---
The next few months are ramping up to be huge in terms of new releases, I’m really looking forward to a few of them particularly the new Alexisonfire record and Moneen’s teaser EP…

A whole bunch of new songs have gone up over the past few days, give them a listen!

**Look Mexico**, they’ve just signed to Suburban Home and are demoing at the moment, a couple are up on their myspace:
[http://www.myspace.com/lookmexico
](http://www.myspace.com/lookmexico) These won’t be up for long I don’t think so listen to them now! These guys will be big!

**Moneen**. New 4 track EP through Dine Alone Records, only available on 12″… Might pick one of these up when I catch them in London in a couple weeks. Album is streaming over at Vinyl Collective:
<http://www.vinylcollective.com/2009/06/02/po-moneen-hold-that-sound-lpfull-ep-stream/>

**Alexisonfire**. I think I’m going to really enjoy this one… judging by the 2 tracks that have surfaced it sounds like they’re shifting away from relying so heavily on Dallas’ vocals and going for a more gruff and raw sound while still doing it different to how they have in the past.  New album out in a month or two, the first new song (_Fallen_) is catchy as hell and incredible live! Another newy, _This Will Be The Death Of Us_, just went up today or yesterday and I’m not quite sold yet but that’s exactly how I felt about Mutiny the first time I listened to it… I have faith in these guys, I know I’ll be picking up that record ASAP.
<http://www.myspace.com/setyourgoals>

And on a completely unrelated note here’s some footage from Sasquatch festival in Washington that a friend who went showed me… This is hilarious! It’ll take about a minute to really kick in but it’s totally worth watching the whole clip!

[youtube=http://www.youtube.com/watch?v=GA8z7f7a2Pk]

repository: mikeolivotto/happy-seizure

gha_language: SCSS

repo_name: mikeolivotto/happy-seizure


text:
---
title: USB Cable Tester
categories:
- projects
tags: []
---

Ever wonder if your USB C cable is USB2 or USB3? Do you have some charge-only cables hiding in a box just waiting for the right moment to spoil your project plans?!
Fear no more!

I’ve made a simple board to test most of the things!

{% include image.html
	img="images/usb_cable_tester/1.jpeg"
	title="USB Cable Tester v2.0 - Front"
	caption="USB Cable Tester v2.0 - Front"
	url="/images/usb_cable_tester/1.jpeg"
%}

{% include image.html
	img="images/usb_cable_tester/2.jpeg"
	title="USB Cable Tester v2.0 - Back"
	caption="USB Cable Tester v2.0 - Back"
	url="/images/usb_cable_tester/2.jpeg"
%}

{% include image.html
	img="images/usb_cable_tester/3.jpeg"
	title="USB Cable Tester v2.0 - Side"
	caption="USB Cable Tester v2.0 - Side"
	url="/images/usb_cable_tester/3.jpeg"
%}

(This post is derived from my original [twitter thread](https://twitter.com/alvaroprieto/status/1594036248481771520) about it.)

## How does it work?

Connect your cable to both sides and the signal LEDs will light up if they are connected. Here’s an example of a USB2 cable and a thunderbolt 3 cable.

{% include image.html
	img="images/usb_cable_tester/4.jpeg"
	title="Testing a USB-C 2.0 Cable"
	caption="Testing a USB-C 2.0 Cable"
	url="/images/usb_cable_tester/4.jpeg"
%}

{% include image.html
	img="images/usb_cable_tester/5.jpeg"
	title="Testing a Thunderbolt 3 Cable"
	caption="Testing a Thunderbolt 3 Cable"
	url="/images/usb_cable_tester/5.jpeg"
%}

Want to test a USB A to C cable? How about a USB A to Micro B? USB C to B? Mini B? You’ve got it!

{% include image.html
	img="images/usb_cable_tester/6.jpeg"
	title="Testing a USB A to C Cable"
	caption="Testing a USB A to C Cable"
	url="/images/usb_cable_tester/6.jpeg"
%}

{% include image.html
	img="images/usb_cable_tester/7.jpeg"
	title="Testing a USB C to B Cable"
	caption="Testing a USB C to B Cable"
	url="/images/usb_cable_tester/7.jpeg"
%}

{% include image.html
	img="images/usb_cable_tester/8.jpeg"
	title="Testing a USB A to Micro B Cable"
	caption="Testing a USB A to Micro B Cable"
	url="/images/usb_cable_tester/8.jpeg"
%}

Here’s what a the dreaded charge-only cables look like. I had to make my own since I had previously banished them from my lab! (These are the real reason I made this)

{% include image.html
	img="images/usb_cable_tester/9.jpeg"
	title="Testing a Charge-only Cable"
	caption="Testing a Charge-only Cable"
	url="/images/usb_cable_tester/9.jpeg"
%}

{% include image.html
	img="images/usb_cable_tester/10.jpeg"
	title="Homemade Charge-only Cable"
	caption="Homemade Charge-only Cable"
	url="/images/usb_cable_tester/10.jpeg"
%}

But….What if my cable is too short!? We have that covered too 😂

{% include image.html
	img="images/usb_cable_tester/11.jpeg"
	title="Testing a short USB 4 Cable"
	caption="Testing a short USB 4 Cable"
	url="/images/usb_cable_tester/11.jpeg"
%}

{% include image.html
	img="images/usb_cable_tester/12.jpeg"
	title="Testing a short USB 4 Cable (Part 2)"
	caption="Testing a short USB 4 Cable (Part 2)"
	url="/images/usb_cable_tester/12.jpeg"
%}

## How can I get one?!
Like most of my projects, the files are available on [the github repo](https://github.com/alvarop/usb_c_cable_tester) under an open hardware license.

If you want to make your own, I have instructions on ordering your own from JLCPCB here: https://github.com/alvarop/usb_c_cable_tester/blob/main/ORDERING.md

## What do all the signals mean?!
I still need to make a nice diagram explaining what you should see for each type of cable. Until then, here's the short version:

All the signals from the USB A connector will show up on the right column of LED's (A1-A12). The "B" side is only used for the USB-C port on the left. The D+/D- signals are the "USB 2.0" data lines. USB-3 will have TX1+/- and RX2+/-.

Every USB-C cable _should_ have either CC1 or CC2 (which will change if you rotate the cable).

## Updates!
You can follow project updates on github. I've released a [new version](https://github.com/alvarop/usb_c_cable_tester/releases/tag/v2.1) with some fixes, but, unfortunately, it still has some issues.


text:
---
layout: post
title: Where Supply Chain Management really matters
tags: [platform, security, dependencies]
---
If you use GitHub you are surely used to this:

![](/images/posts/2022-04-06_21-01-08.png)

Nowadays we are starting to take supply chain management for granted. Unfortunately it is a tendency as an industry - instead of focusing on remediating and improving our existing code, we treat it as a nuisance only focusing on what's next.

However new, shiny code doesn't really matter if you are reading this, and if you are running a full-fledged DevOps practice you will quickly realise that there is so much work fo do when it comes to introducing Supply Chain Management in an organisation. If you are using GitHub then great, Dependabot gives you a great headstart by integrating with the platform and continuously scanning your code. However, what if you use _something else_?

There are so many tools on the market for this: Whitesource, Snyk, etc. Even SonarQube can do Software Composition Analysis (another name for Supply Chain Management) via an [OWASP plugin](https://github.com/dependency-check/dependency-check-sonar-plugin). It goes to show how important this topic is and how much choice there is if you want to make things right.

The reason why it is really important is because your _legacy code_ is most likely running in production. Like the vast majority of us, I have a number of repositories with legacy code. This sample application was written in .NET Core 1.1, and it's been last updated in October 2017. If you never ran anything like Snyk or Whitesource, you will naturally find something akin to this state.

![](/images/posts/2022-04-06_21-18-49.png)

![](/images/posts/2022-04-06_21-16-46.png)

Some of these vulnerabilities can be easily fixed by a version bump, however others would require a complete runtime change, a migration, etc. A Supply Chain Management tool combined with your Engineering Platform will go a long way in making sure that your organisation remains sustainable.

Personally, I really like [Snyk](https://snyk.io). I used all of the tools above for years, and as of today it is the one that in my view gives the most comprehensive experience with the least amount of friction. You can set it up in minutes, and if you are targeting Azure DevOps it gives you so much power directly into the platform.

![](/images/posts/2022-04-06_21-23-56.png)

I really found beneficial having an easy way of raising Pull Requests from outside Team Projects so that development teams can benefit from them. It is also quite smart in understanding what can be easily fixed and what can't, as well as giving you so much information about the issues at hand:

![](/images/posts/2022-04-06_21-26-38.png)

In my case above there is little point in raising a PR this way, however with more recent systems it provides you with an easy way of approaching a remediation without involving too intensive efforts. Of course every time you look at something running in production you might not be able to just update the code dependencies, but that's a story for another day...

gha_language: HTML


text:
(translated by runningwater)
Test read/write speed of usb and ssd drives with dd command on Linux
================================================================================
### Drive speed ###

The speed of a drive is measured in terms of how much data it can read or write in unit time. The dd command is a simple command line tool that can be used to read and write arbitrary blocks of data to a drive and measure the speed at which the data transfer took place.

In this post we shall use the dd command to test and read and write speed of usb and ssd drives using the dd command.

The data transfer speed does not depend solely on the drive, but also on the interface it is connected to. For example a usb 2.0 port has a maximum operational speed limit of 35 Mbytes/s, so even if you were to plug a high speed usb 3 pen drive into a usb 2 port, the speed would be capped to the lower limit.

The same applies to SSD. SSD connect via SATA ports which have different versions. Sata 2.0 has a maximum theoretical speed limit of 3Gbits/s which is roughly 375 Mbytes/s. Whereas Sata 3.0 supports twice that speed.

### Test Method ###

Mount the drive and navigate into it from the terminal. Then use the dd command to first write a file using fixed sized blocks. Then read the same file out using the same block site.

The general syntax of the dd command looks like this

    dd if=path/to/input_file of=/path/to/output_file bs=block_size count=number_of_blocks

When writing to the drive, we simply read from /dev/zero which is a source of infinite useless bytes. And when read from the drive, we read the file written earlier and send it to /dev/null which is nowhere. In the whole process, dd keeps track of the speed with which the transfer takes place and reports it.

### SSD ###

The SSD that we are using is a "Samsung Evo 120GB" ssd. It is a beginner level ssd that comes within a decent budget and is also my first SSD. It is also one of the best performing ssds, in the market.

In this test the ssd is connected to a sata 2.0 port.

#### Write speed ####

Lets first write to the ssd

    $ dd if=/dev/zero of=./largefile bs=1M count=1024
    1024+0 records in
    1024+0 records out
<PHONE_NUMBER> bytes (1.1 GB) copied, 4.82364 s, 223 MB/s

Block size is actually quite large. You can try with smaller sizes like 64k or even 4k.

#### Read speed ####

Now read back the same file. However, first clear the memory cache to ensure that the file is actually read from drive.

Run the following command to clear the memory cache

    $ sudo sh -c "sync && echo 3 > /proc/sys/vm/drop_caches"

Now read the file

    $ dd if=./largefile of=/dev/null bs=4k
    165118+0 records in
    165118+0 records out
    676323328 bytes (676 MB) copied, 3.0114 s, 225 MB/s

The Arch Linux wiki has a page full of information about the read/write speed of various SSDs from different vendors like Intel, Samsung, Sandisk etc. Check it out at the following url.

[https://wiki.archlinux.org/index.php/SSD_Benchmarking][1]

### USB ###

In this test we shall measure the read and write speed of ordinary usb/pen drives. The drives are plugged to standard usb 2 ports. The first one is a sony 4gb usb drive and the second is a strontium 16gb drive.

First plug the drive into the port and mount it, so that it is readable. Then navigate into the mount directory from the command line.

#### Sony 4GB - Write ####

In this test, the dd command is used to write 10,000 chunks of 8 Kbyte each to a single file on the drive.

    # dd if=/dev/zero of=./largefile bs=8k count=10000
    10000+0 records in
    10000+0 records out
    81920000 bytes (82 MB) copied, 11.0626 s, 7.4 MB/s

So the write speed is around 7.5 MBytes/s. This is a low figure.

#### Sony 4GB - Read ####

The same file is read back to test the read speed. Run the following command to clear the memory cache

    $ sudo sh -c "sync && echo 3 > /proc/sys/vm/drop_caches"

Now read the file using the dd command

    # dd if=./largefile of=/dev/null bs=8k
    8000+0 records in
    8000+0 records out
    65536000 bytes (66 MB) copied, 2.65218 s, 24.7 MB/s

The read speed comes out around 25 Mbytes/s which is a more or less the standard for cheap usb drives.

> USB 2.0 has a theoretical maximum signaling rate of 480 Mbits/s or 60 Mbytes/s. However due to various constraints the maximum throughput is restricted to around 280 Mbit/s or 35 Mbytes/s. Beyond this the actual speed achieved depends on the quality of the pen drives and other factors too.

And the above usb drive was plugged inside a USB 2.0 port and it achieved a read speed of 24.7 Mbytes/s which is not very bad. But the write speed lags much behind

Now lets do the same test with a Strontium 16gb drive. Strontium is another very cheapy brand, although usb drives are reliable.

#### Strontium 16gb write speed ####

    # dd if=/dev/zero of=./largefile bs=64k count=1000
    1000+0 records in
    1000+0 records out
    65536000 bytes (66 MB) copied, 8.3834 s, 7.8 MB/s

Strontium 16gb read speed

    # sudo sh -c "sync && echo 3 > /proc/sys/vm/drop_caches"

    # dd if=./largefile of=/dev/null bs=8k
    8000+0 records in
    8000+0 records out
    65536000 bytes (66 MB) copied, 2.90366 s, 22.6 MB/s

The read speed is lower than the Sony drive.

### Resources ###

- [http://en.wikipedia.org/wiki/USB][2]
- [https://wiki.archlinux.org/index.php/SSD_Benchmarking][1]

----------

![](http://0.gravatar.com/avatar/e23f2767e6907e798da5b28694a2bf28?s=64&d=&r=G)

About Silver Moon

Php developer, blogger and Linux enthusiast. He can be reached at<EMAIL_ADDRESS>Or find him on [Google+][g]

--------------------------------------------------------------------------------

via: http://www.binarytides.com/linux-test-drive-speed/

译者：[runningwater](https://github.com/runningwater) 校对：[校对者ID](https://github.com/校对者ID)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译，[Linux中国](http://linux.cn/) 荣誉推出

[1]:http://wiki.archlinux.org/index.php/SSD_Benchmarking
[2]:http://en.wikipedia.org/wiki/USB
<EMAIL_ADDRESS>[g]:http://plus.google.com/117145272367995638274/posts

url: https://raw.githubusercontent.com/nkhuyu/TranslateProject/a1abfe2448d0ed8db0d88d3a836d2f94b43f55ad/sources/tech/20140714 Test read or write speed of usb and ssd drives with dd command on Linux.md

repository: nkhuyu/TranslateProject

repo_name: nkhuyu/TranslateProject


text:
WebApi In Memory Acceptance Tests
==============================

In memory acceptance test examples for owin based web api projects.

This shows how owin can be used to run acceptance tests that would normally need to be ran on a server directly in memory. This leads to:

* big speed boosts
* The ability to debug both the test and the target at the same time
* You can alter your code (e.g ioc) directly from your test.

The simple tests have no requirements but the mongo tests will require a locally running instance of mongo db.


text:
# RELEASE

1. `npm version patch|minor|major` (depending on what kind of release it is)
2. `npm publish`
3. Update links in README.md with new version number


text:
---
layout: default
---

# 1998-12-15 - Re: Anyone Striking?

## Header Data

From: Missouri FreeNet Administration<EMAIL_ADDRESS>To: James Glave<EMAIL_ADDRESS>Message Hash: 7d9d11175b6d338589df69de89db2e37bfaa21d935990c44cdc3474ae282935f

Message ID<EMAIL_ADDRESS>Reply To<EMAIL_ADDRESS>UTC Datetime: 1998-12-15 00:30:22 UTC

Raw Date: Tue, 15 Dec 1998 08:30:22 +0800

## Raw message

```
{% raw  %}From: Missouri FreeNet Administration<EMAIL_ADDRESS>Date: Tue, 15 Dec 1998 08:30:22 +0800
To: James Glave<EMAIL_ADDRESS>Subject: Re: Anyone Striking?
In-Reply-To<EMAIL_ADDRESS>Message-ID<EMAIL_ADDRESS>MIME-Version: 1.0
Content-Type: text/plain

We just returned from this.  Feel free to ask whatever you'd like.

Yours,
J.A. Terranson
<EMAIL_ADDRESS>
--
If Governments really want us to behave like civilized human beings, they
should give serious consideration towards setting a better example:
Ruling by force, rather than consensus; the unrestrained application of
unjust laws (which the victim-populations were never allowed input on in
the first place); the State policy of justice only for the rich and
elected; the intentional abuse and occassionally destruction of entire
populations merely to distract an already apathetic and numb electorate...
This type of demogoguery must surely wipe out the fascist United States
as surely as it wiped out the fascist Union of Soviet Socialist Republics.

The views expressed here are mine, and NOT those of my employers,
associates, or others.  Besides, if it *were* the opinion of all of
those people, I doubt there would be a problem to bitch about in the
first place...
--------------------------------------------------------------------

On Mon, 14 Dec 1998, James Glave wrote:

:Date: Mon, 14 Dec 1998 07:29:32 -0800
:From: James Glave<EMAIL_ADDRESS>:To: Robert Hettinga<EMAIL_ADDRESS>:Cc<EMAIL_ADDRESS><EMAIL_ADDRESS><EMAIL_ADDRESS>:Subject: Anyone Striking?
:
:Anyone participating in the strike today? I'd like to possibly visit this
:with a news story...
:
:jtg
:
:At 03:10 PM 12/10/98 -0500, Robert Hettinga wrote:
:>At 9:05 AM -0500 on 12/10/98, Ken Williams wrote:
:>
:>> "Strike to protest Wassenaar!"
:>>
:>> URL:  http://www.zanshin.com/~bobg/
:>>
:>> "This is a global call for computer professionals to strike on
:>> Monday, 14 December, 1998 to protest the signing of the Wassenaar
:>> Arrangement, an international treaty that imposes new restrictions
:>> on cryptographic software technology.
:>
:>Now, *this* is interesting...
:>
:>Anyone actually contemplating doing this?
:
:
:James Glave, News Editor, Wired News, http://www.wired.com  +1<PHONE_NUMBER>
:

{% endraw %}
```

## Thread

+ Return to [December 1998](/archive/1998/12)

+ Return to "[James Glave <james@wired.com>](/authors/james_glave_james_at_wired_com_)"
+ Return to "[Ken Williams <jkwilli2@unity.ncsu.edu>](/authors/ken_williams_jkwilli2_at_unity_ncsu_edu_)"
+ Return to "[Kevlar <webmaster@max-web.com>](/authors/kevlar_webmaster_at_maxweb_com_)"
+ Return to "[Missouri FreeNet Administration <measl@mfn.org>](/authors/missouri_freenet_administration_measl_at_mfn_org_)"
+ Return to "["Perry E. Metzger" <perry@piermont.com>](/authors/perry_e_metzger_perry_at_piermont_com_)"
+ Return to "[Rabid Wombat <wombat@mcfeely.bsfs.org>](/authors/rabid_wombat_wombat_at_mcfeely_bsfs_org_)"
+ Return to "[Robert Hettinga <rah@shipwright.com>](/authors/robert_hettinga_rah_at_shipwright_com_)"
+ Return to "[Steve Orrin <privsoft@ix.netcom.com>](/authors/steve_orrin_privsoft_at_ix_netcom_com_)"
+ Return to "[Sunder <sunder@brainlink.com>](/authors/sunder_sunder_at_brainlink_com_)"
+ Return to "[The Sheriff <sheriff@speakeasy.org>](/authors/the_sheriff_sheriff_at_speakeasy_org_)"
+ Return to "["William H. Geiger III" <whgiii@openpgp.net>](/authors/william_h_geiger_iii_whgiii_at_openpgp_net_)"
+ Return to "["William J.Hartwell" <billh@ibag.com>](/authors/william_j_hartwell_billh_at_ibag_com_)"

+ 1998-12-10 (Thu, 10 Dec 1998 06:06:14 -0800 (PST)) - [Global Strike to protest Wassenaar](/archive/1998/12/a8cc59bffc94ad28057dc4b58b332ce523aee542beb8125c7d7e6f333246a09e) - _Ken Williams<EMAIL_ADDRESS>  + 1998-12-10 (Fri, 11 Dec 1998 01:16:12 +0800) - [Re: Global Strike to protest Wassenaar](/archive/1998/12/d46ef828b76b04737200f3ee76483b09d042319fa03e07f10342ca52836e9fe3) - _Missouri FreeNet Administration<EMAIL_ADDRESS>    + 1998-12-11 (Thu, 10 Dec 1998 16:22:25 -0800 (PST)) - [Re: Global Strike to protest Wassenaar](/archive/1998/12/cb28625e70b42714ed7565ce8bd7e588eb97eae4d91d74b610caa8d48e67cb43) - _Steve Orrin<EMAIL_ADDRESS>      + 1998-12-11 (Thu, 10 Dec 1998 19:18:34 -0800 (PST)) - [Re: Global Strike to protest Wassenaar](/archive/1998/12/98db212056905a219189e31910e23098c00b85020c670865766ff92b45ba2f28) - _Missouri FreeNet Administration<EMAIL_ADDRESS>  + 1998-12-10 (Thu, 10 Dec 1998 12:13:37 -0800 (PST)) - [Re: Global Strike to protest Wassenaar](/archive/1998/12/23841f976c29b0cb402cf124d3ca7b44fda265fd6ab985fa4c792376b1ef74ea) - _Robert Hettinga<EMAIL_ADDRESS>    + 1998-12-14 (Tue, 15 Dec 1998 01:18:20 +0800) - [Re: Anyone Striking?](/archive/1998/12/258b0d0c146c15f7898c4ab3668237fa95831b9946c15a2a4b0860baf0cba862) - _Robert Hettinga<EMAIL_ADDRESS>  + 1998-12-11 (Thu, 10 Dec 1998 16:36:06 -0800 (PST)) - [Re: Global Strike to protest Wassenaar](/archive/1998/12/28118cbd735a9c088c6c8e66bf7dc2c171e1322ce894cd6fdd3f7b199073cedb) - _Kevlar<EMAIL_ADDRESS>    + 1998-12-11 (Thu, 10 Dec 1998 21:11:46 -0800 (PST)) - [Re: Global Strike to protest Wassenaar](/archive/1998/12/b86b6e0ebc6c7d801d5335c1c87a72ca96a873fe3d7c99377ac89b8fa6c945d9) - _"William H. Geiger III"<EMAIL_ADDRESS>    + 1998-12-12 (Sun, 13 Dec 1998 01:34:24 +0800) - [Re: Global Strike to protest Wassenaar](/archive/1998/12/a8ec5bd21749a5ce69e23a443802c4292072d6ea99f6d77ba0ef97d551a80926) - _The Sheriff<EMAIL_ADDRESS>  + 1998-12-14 (Tue, 15 Dec 1998 00:23:55 +0800) - [Anyone Striking?](/archive/1998/12/f5387e631b99cf40311a103b1e57388671e24a32797f0d4d6d1c5d93498ec5ed) - _James Glave<EMAIL_ADDRESS>    + 1998-12-14 (Tue, 15 Dec 1998 00:55:14 +0800) - [Re: Anyone Striking?](/archive/1998/12/3d178dc4d240e73918a6b35626f1095e142ec1759cddf92e87bc60c4fcd28215) - _"Perry E. Metzger"<EMAIL_ADDRESS>      + 1998-12-14 (Tue, 15 Dec 1998 01:17:44 +0800) - [Re: Anyone Striking?](/archive/1998/12/394b4751be10b32ff49421cf3022ccba94137171169fa459d3e1c5400c3bbd7c) - _Sunder<EMAIL_ADDRESS>    + 1998-12-14 (Tue, 15 Dec 1998 03:45:28 +0800) - [Re: Anyone Striking?](/archive/1998/12/e76235cd2322438fff04c8a614c386dc78481439a6a17ed2c9fffbc3043cc668) - _"William J.Hartwell"<EMAIL_ADDRESS>      + 1998-12-15 (Tue, 15 Dec 1998 09:23:23 +0800) - [Re: Anyone Striking?](/archive/1998/12/c3274cc689cc7a3fe57aca6c4b116a113f06f53722d0bea150c38b550a1f9d60) - _Rabid Wombat<EMAIL_ADDRESS>    + 1998-12-15 (Tue, 15 Dec 1998 08:30:22 +0800) - Re: Anyone Striking? - _Missouri FreeNet Administration<EMAIL_ADDRESS>


text:
---

copyright:
  years: 2015, 2016

---

{:new_window: target="_blank"}
{:shortdesc: .shortdesc}
{:screen:.screen}
{:codeblock:.codeblock}

# Using the {{site.data.keyword.weather_short}} REST APIs
{: #rest_apis}

Last updated: 22 August 2016
{: .last-updated}

You can use the [REST APIs](https://twcservice.{APPDomain}/rest-api/){:new_window}
to retrieve weather data. You can test API operations and instantly view the results
to help you build your applications faster.
{: shortdesc}

From the reference documentation, click **List Operations** to view details of each operation.
When you specify parameters and click **Try it out!**, you might be asked to provide credentials.
You must provide the user name and password from your `VCAP_SERVICES` environment variables.
You can find this information by opening your application and clicking **Environment Variables** from the table of contents.

**Note:** Each region is independent. You cannot use service credentials
that are provisioned to you in one region to authenticate to a service in another region.
Failure to enter proper credentials results in an *Unauthorized* message in the response body.

With the REST APIs, you can retrieve weather data by supplying a geolocation as latitude and longitude coordinates.
You can use the following APIs.

|**API**                                  |**Description**              |
|-----------------------------------------|-----------------------------|
|`GET /v1/{geocode or location ID}/forecast/hourly/48hour.json`  |Returns the hourly weather forecast for the next 48 hours for a geolocation depending on the format that you supply. You can supply a `geocode/{latitude}/{longitude}` or a `location/{locationId}`. The hourly forecast data can contain up to 48 hourly forecasts for each location. You must discard all previous hourly forecasts for a location when new data is received.|
|`GET /v1/{geocode or location ID}/forecast/daily/{format}.json`   |Returns daily weather forecasts for 3, 5, 7, or 10 days for a geolocation depending on the format that you supply. The number of days to be retrieved is specified in the format as `3day`, `5day`, `7day`, or `10day`. You can supply a `geocode/{latitude}/{longitude}` or a `location/{locationId}`. Each daily forecast can contain a daytime forecast, a nighttime forecast, and a 24-hour forecast. These segments are separate objects in the JSON responses. Daytime forecast data of the daily forecast is no longer available after 3:00 PM local time. At 3:00 PM local time, your application must no longer display the day forecast.|
|`GET /v1/{geocode or location ID}/forecast/intraday/{format}.json`|Returns daily weather forecasts in six-hour periods for 3, 5, 7, or 10 days for a geolocation depending on the format that you supply. The number of days to be retrieved is specified in the format as `3day`, `5day`, `7day`, or `10day`. You can supply a `geocode/{latitude}/{longitude}` or a `location/{locationId}`. Each daily forecast can contain a morning, afternoon, evening, and overnight forecast. These segments are separate objects in the JSON responses.|
|`GET /v1/{geocode or location ID}/observations.json`              |Returns the current weather conditions for a geolocation. You can supply a `geocode/{latitude}/{longitude}` or a `location/{locationId}`.  These recent observations are retained in the database up to 10 minutes on specific reporting stations and 24 hours of observations per station. The recent observations data is continuously updated and replaced with a first-in / first-out methodology (rotating data with newest observation and moving the oldest observations to the archive storage) based on date/time stamping of the observations.|
|`GET /v1/{geocode or location ID}/observations/timeseries.json`   |Returns both the current observations and up to 24 hours of past observations, from the current date and time, for a geolocation. You can supply a `geocode/{latitude}/{longitude}` or a `location/{locationId}`. Weather observations are gathered from physical devices deployed worldwide, and the current weather observations.|
|`GET /v1/{geocode, country code, state, or area}/alerts.json`      |Returns weather watches, warnings, statements, and advisories that are issued by the National Weather Service (NWS), Environment Canada, and MeteoAlarm (Europe) and include the translation of the event description, country name, and alert headlines in 49 languages. You can supply a `geocode/{latitude}/{longitude}`, `country/{countrycode}`, `country/{countrycode}/state/{statecode}`/, or `country/{countrycode}/area/{areaid}`.|
|`GET /v1/alert/{detail_key}/details.json`                         |Returns weather watches, warnings, statements, and advisories that are issued by the National Weather Service (NWS), Environment Canada, and MeteoAlarm (Europe). The details include in-depth information about the alert that is issued by the government weather authority for the specified area and include the translation of the event description, country name, and alert headlines in 49 languages.|
|`GET /v1/{geocode or postal code}/almanac/daily.json`             |Returns daily almanac information (US only) that is sourced from National Weather Service observations stations from a time period spanning 10 to 30 years or more. The information is gathered and provided by the National Climatic Data Center (NCDC). You can supply a `geocode/{latitude}/{longitude}`, or `location/{PostalLocationId}`.|
|`GET /v1/{geocode or postal code}/almanac/monthly.json`           |Returns monthly almanac information (US only) that is sourced from National Weather Service observations stations from a time period spanning 10 to 30 years or more. The information is gathered and provided by the National Climatic Data Center (NCDC). You can supply a `geocode/{latitude}/{longitude}`, or `location/{PostalLocationId}`.|
|`GET /v3/location/{search or point}`                                  |Provides the ability to look up a location name or geocode (latitude and longitude) to retrieve a set of locations that match the request. The Location Service supports search by city name or postal code.|
*Table 1. {{site.data.keyword.weather_short}} API summary*

## Daily and intraday forecasts
{: #daily_intraday}
The daily forecast API can contain multiple days of daily forecasts for each location.
Each day of a forecast can contain up to three separate forecasts. For any
forecast day, the API can return day, night, and 24-hour forecasts.

The intraday forecast API can contain multiple days of daily forecasts for each location.
Each day of a forecast contains four separate six-hour forecasts for morning (7 AM to 1 PM),
afternoon (1 PM to 7 PM), evening (7 PM to 1 AM), and overnight (1 AM to 7 AM). The
intraday forecast is similar in structure to the daily forecast.

Each segment has a day part number, day of the week name, and day part name. For example,
the following example shows the data field order and data values for
`num`, `dow`, and the `daypart_name`, for a forecast that is generated
by the APIs on a Thursday morning:
* 1, Thursday, Morning
* 2, Thursday, Afternoon
* 3, Thursday, Evening
* 4, Thursday, Overnight
* 5, Friday, Morning
* 6, Friday, Afternoon
* 7, Friday, Evening
* 8, Friday, Overnight

## Current and time-series observations
{: #time_series}

The current conditions and time-series weather observations data provides information about temperature,
precipitation, wind, barometric pressure, visibility, ultraviolet (UV) radiation,
and other related observation elements, including observation station,
observation date/time, weather icon codes and phrases. The difference between
time-series observations and current observations is the time period
of the observation, which results in one or more observation data sets.

The current conditions are the most recent observations for the location that is
requested with no time parameter. One data set is returned. The time-series
observations include past observations that occurred up to and including the
last 24 hours for the location requested.

Recent observations are retained in the primary database up to 48 hours (2 days)
on specific reporting stations. The recent observations data is continuously
updated and replaced with a first-in/first-out methodology (rotating data with
newest observation and moving the oldest observations to the archive storage)
based on date/time stamping of the observations. The amount of data that is
retained and available from any station can be more than 24 individual
observation reports. The number of observations is
determined by the type of observation it is.

## Alert headlines and details
{: #alerts_levels}
The alert APIs return active weather alert headlines that are related to severe
thunderstorms, tornadoes, earthquakes, and floods.
These APIs also return non-weather alerts such as child abduction alerts and
law enforcement warnings.

**Note**: This API is available only for the United States, Canada, and Europe.

The Alert Headlines API provides a key value in the `detail_key` attribute
to access the alert details in the Alert Details API.
Query the Alert Headlines API to get the `detail_key` value, and then retrieve the
Alert Details API response with the `detail_key`.

**Note**: You must display the data source attribution for any alert data that is displayed in your application.

The attribution phrase must display the following information:

*Issued by <Office Name> - <Office Admin District Code>, <Office Country Code>, <Source>, <Disclaimer>*

For example:
* Issued by National Weather Service - Bismarck, US
* Issued by Central Institute for Meteorology and Geodynamics - Austria, EMETNET-Meteoalarm

## Almanac information
{: #almanac_details}
The Almanac API requires a location ID and location type (city or postal code)
or a latitude and longitude pair to retrieve the information for a specific location.

When you use `location` in the URL, the location must include a location ID
(postal code) with a location type and a
country code. When you use `geocode` in the URL, the search location must be a valid
latitude and longitude combination.

The Almanac API uses parameters to specify either daily or monthly data,
a specific date or date range of information, and the units of measure to return the data in.

The date parameters are `start` and `end`. The `start` parameter is a required parameter
but the `end` parameter is optional. When the parameters are used together, the combination returns a
range of data instead of a specific month or day of data.

The date format for retrieving Daily Almanac results is a four-digit numeric value that represents
the month and day for the data required, that is, MMDD. Any single digit
day **must** have a preceding zero, for example, 01.

The date format for retrieving Monthly Almanac results is month, that is, MM. Any single digit
month **must** have a preceding zero, for example, 01. Any other format results in
an API error and no data will be returned.

**Note**: If you don't provide the date value in the request, the system returns a
status of 404 (Bad Request). The API does not provide a default value.

## URL construction
{: #url_construction}

The REST APIs use a common URL structure and query parameters to request and filter weather data.
The URLs that are passed to the APIs are constructed as follows:

```
https://twcservice.mybluemix.net/api/weather/v1/geocode/<latitude>/<longitude>/<product group>/<date>/<format>&units={units code}&language={language code}
```

For example:

```
https://twcservice.mybluemix.net/api/weather/v1/geocode/33.40/83.42/forecast/daily/3day.json?units=m&language=en-US
```

|**Attribute**     |**Description**                                    |
|------------------|---------------------------------------------------|
|`hostname`        |The hosted URL path. For example, `https://twcservice.mybluemix.net:443/api/weather`.|
|`version`         |The current iteration. For example, `v1`.|
|`location`        |The geocode or location ID. The location group can be `geocode` or `location`. For example, `geocode/45.4214/75.6919` represents Ottawa, Canada. If you supply a geocode coordinate, the API returns data for the closest location available. Periods are used as decimal separators and commas are used to separate latitude and longitude values. If you supply a geocode, the actual latitude and longitude values that are used are returned in the metadata of the response.|
|`product group`   |The product. For example, `observations` or `forecast`. A product subgroup, for example, `historical`, is optional.|
|`date`            |The date type. For example, `daily` or `monthly`.|
|`format`          |The format. For example, `3day`, `5day`, `7day`, or `10day`.|
|`units`           |The optional units to return the response in. The API supports English (e), Metric (m), and UK-Hybrid (h) units of measure. If you supply the units of measure but don't supply a value, the API returns the data in the unit of measure that corresponds to the language code. The default or requested unit of measure is returned in the units parameter in the metadata of the response.|
|`language`        |The language to return the response in. The default is en-US. The default or requested translation language is returned in the language parameter in the metadata of the response.|
*Table 2. URL details*

**Note**: The REST APIs use the ISO 3166 standard for country codes. For more information, see the
[ISO Standard Online Browsing Platform](https://www.iso.org/obp/ui/#search/code/){:new_window}.
The APIs use the WGS84 geocode coordinate reference system. For more information, see
[Basic Geo Vocabulary](https://www.w3.org/2003/01/geo/){:new_window}.

## Icon codes and images
{: #icon_code_images}

When the {{site.data.keyword.weather_short}} REST APIs return an icon code in the response,
you can use the icon code to determine which icon image to display in your app.
There is a one to one relationship between the icon code in the API response and the file name of the icon image.
For example, if the API response contains an `icon_code` of 1, you can use the file name `01.png`
to display the matching icon image.

In your code, you can create a function that uses the `icon_code` to determine
the URL of the icon image. For example:

```
function getIconURL(code) {
    return "images/weathericons/icon" + code + ".png";
}
```

The following table contains icon codes, descriptions, and images that can be used
with the {{site.data.keyword.weather_short}} REST APIs. The table indicates whether an icon
is used in the Forecast or Observation APIs and whether the icon is available in Night or Daytime
forecast parts.

|**Code**|**Description**|**Image**|**API usage** |**Night or Daytime**|
|----|--------------------------|------------|------------|--------------------|
| 0  | Tornado                  | | Forecast                | Night and Day |
| 1  | Tropical Storm           | | Forecast and Observations | Night and Day |
| 2  | Hurricane                | | Forecast                | Night and Day |
| 3  | Strong Storms            | | Forecast                | Night and Day |
| 4  | Thunder and Hail         | | Forecast and Observations | Night and Day |
| 5  | Rain to Snow Showers     | | Forecast and Observations | Night and Day |
| 6  | Rain / Sleet             | | Forecast and Observations | Night and Day |
| 7  | Wintry Mix Snow / Sleet  | | Forecast and Observations | Night and Day |
| 8  | Freezing Drizzle         | | Forecast and Observations | Night and Day |
| 9  | Drizzle                  | | Forecast and Observations | Night and Day |
| 10 | Freezing Rain            | | Forecast and Observations | Night and Day |
| 11 | Light Rain               | | Forecast and Observations | Night and Day |
| 12 | Rain                     | | Forecast and Observations | Night and Day |
| 13 | Scattered Flurries       | | Forecast and Observations | Night and Day |
| 14 | Light Snow               | | Forecast and Observations | Night and Day |
| 15 | Blowing / Drifting Snow  | | Forecast and Observations | Night and Day |
| 16 | Snow                     | | Forecast and Observations | Night and Day |
| 17 | Hail                     | | Forecast and Observations | Night and Day |
| 18 | Sleet                    | | Forecast and Observations | Night and Day |
| 19 | Blowing Dust / Sandstorm | | Forecast and Observations | Night and Day |
| 20 | Foggy                    | | Forecast and Observations | Night and Day |
| 21 | Haze / Windy             | | Forecast and Observations | Night and Day |
| 22 | Smoke / Windy            | | Forecast and Observations | Night and Day |
| 23 | Breezy                   | | Forecast                | Night and Day |
| 24 | Blowing Spray / Windy    | | Forecast and Observations | Night and Day |
| 25 | Frigid / Ice Crystals    | | Forecast and Observations | Night and Day |
| 26 | Cloudy                   | | Forecast and Observations | Night and Day |
| 27 | Mostly Cloudy            | | Forecast and Observations | Night and Day |
| 28 | Mostly Cloudy            | | Forecast and Observations | Day         |
| 29 | Partly Cloudy            | | Forecast and Observations | Night       |
| 30 | Partly Cloudy            | | Forecast and Observations | Day         |
| 31 | Clear                    | | Forecast and Observations | Night       |
| 32 | Sunny                    | | Forecast and Observations | Day         |
| 33 | Fair / Mostly Clear      | | Forecast and Observations | Night       |
| 34 | Fair / Mostly Sunny      | | Forecast and Observations | Day         |
| 35 | Mixed Rain & Hail        | | Forecast                | Day         |
| 36 | Hot                      | | Forecast                | Day         |
| 37 | Isolated Thunderstorms   | | Forecast                | Day         |
| 38 | Thunderstorms            | | Forecast and Observations | Night and Day |
| 39 | Scattered Showers        | | Forecast                | Day         |
| 40 | Heavy Rain               | | Forecast and Observations | Night and Day |
| 41 | Scattered Snow Showers   | | Forecast                | Day         |
| 42 | Heavy Snow               | | Forecast and Observations | Night and Day |
| 43 | Blizzard                 | | Forecast                | Night and Day |
| 44 | Not Available (N/A)      | | Forecast                | Night and Day |
| 45 | Scattered Showers        | | Forecast                | Night       |
| 46 | Scattered Snow Showers   | | Forecast                | Night       |
| 47 | Scattered Thunderstorms  | | Forecast and Observations | Night and Day |
*Table 3. Icon codes and images*

You can download this set of weather icons as [PNGs](https://twcdocs.mybluemix.net/download/weather_icons_200x200_png.zip){:new_window}
or [SVGs](https://twcdocs.mybluemix.net/download/weather_icons_200x200_svg.zip){:new_window} and use them your app.

You can also download the [set of icons](https://twcdocs.mybluemix.net/download/weatherinsightsicons.zip){:new_window} that the
[{{site.data.keyword.weather_short}} demo app](http://weather-company-data-demo.{APPDomain}){: new_window} uses.

## Units of measure
{: #units_measure}

When you use the REST APIs, you don't need to explicitly pass a unit of measure. The APIs default to the unit of measure that is associated with the language code in the URL. However, if you want to provide a unit of measure that is different from the default, you can pass in a unit of measure that overrides the default.

* For en-US or en, the default unit of measure code is English/Imperial. The unit code is `e`.
* For en-GB, the default unit of measure is Hybrid-UK. The unit code is `h`.
* For everything else, the default unit of measure is Metric. The unit code is `m`.

## Language translation
{: #language_translation}

The REST APIs translate the phrases and unit of measure. When you format a request URL, you must provide a valid language.
The following fields are translated:

|**Field**           |**Description**                                    |
|--------------------|---------------------------------------------------|
|`narrative`         |The narrative forecast for the 24-hour period|
|`dow`               |Day of week|
|`wind_phrase`       |The phrase that describes the wind direction and speed for a 12-hour daypart|
|`wdir_cardinal`     |Daytime average wind direction in cardinal notation|
|`daypart_name`      |The name of a 12-hour daypart not including day names in the first 48 hours|
|`temp_phrase`       |The short phrase that contains the forecasted high or low temperature for 12-hour forecast period|
|`shortcast`         |An abbreviated sensible weather portion of narrative forecast|
|`long_daypart_name` |The named time frame for the valid weather forecast in an expanded format. The named time frame can be either for 12-hour periods or 24-hour periods.|
|`golf_category`     |The golf index category that is expressed as a phrase for the weather conditions for playing golf|
|`phrase_nnchar`     |Daytime sensible weather phrase|
|`lunar_phrase`      |Three-character short code for lunar phases|
|`uv_desc`           |The UV index description, which complements the UV index value by providing an associated level of risk of skin damage due to exposure|
|`wx_phrase`         |A text description of the observed weather conditions at the reporting station.|
|`pressure_desc`     |A phrase that describes the change in the barometric pressure reading over the last hour.|
|`headline_text`     |The text of the headline of an event for the location.|
|`event_desc`        |A description of an event.|
|`cntry_name`        |The country name where an event occurred, given in mixed case letters.|
*Table 4. Translated response fields*

## Handling null or missing data fields in the API response
{: #handling_null_or_missing}

If a data field is null because the data is not available, the REST APIs either return the appropriate field tags with the word `null` or don't return the field at all.

## Handling errors
{: #handling_errors}

The following error codes are common to all APIs:

|**Error** |**Description**                                    |
|----------|---------------------------------------------------|
|400       |Bad request. The request was not understood by the server due to malformed syntax. This error code is implemented for all APIs. API rejects the request if any invalid parameters are supplied.|
|401       |Unauthorized. The request requires authentication.|
|403       |Forbidden. The server understood the request but is refusing to fulfill it.|
|404       |Not found. If a required parameter is not present in the API request, a MissingParameterException error with a 404 error code is returned.|
|500       |Internal server error. The server encountered an unexpected condition that prevented it from fulfilling the request.|
*Table 5. Error response code*

The response on error is always the same. Multiple error codes can be returned in one response.
For example, a JSON error response might be returned as follows:

```
{
  metadata: {
    transaction_id: "1411496413365:-1880721071"
  },
  success: false,
  errors: [
    {
      error: {
        code: "NDF-0001",
        message: "There was no data found for your product query."
      }
    }
}
```

repository: kKronstainBrown/docs

repo_name: kKronstainBrown/docs


text:
---
title: 'UI Performance Metrics: Time to Interactive vs Dom Interactive'
subtitle: 'TTI vs DOM Interactive'
date: '2020-12-11'
topic: 'Performance'
tags: ['performance']
description: 'We might have different ideas about what that means and certanly that is the case between time to interactive and dom Interactive'
language: 'en'
hideImgTitle: false
---

Implying "Interactivity" in the naming can be problematic. We might have different ideas about what that means and certainly that is the case between time to interactive and dom Interactive.

These two metrics try to give you an indication of how much time you need to wait until a page it's interactive, the main difference is that depending on the characteristics of your page the accuracy of each metric will defer.

## The main difference

**[Time to interactive](/2020/ui-performance-metrics-what-is-time-to-interactive/)** always waits until your main thread is almost idle and because of that reason always comes later than Dom interactive. Time to interactive is an approximation type of metric and can defer based on its implementation.

**Dom interactive** indicates a specific moment in which _the browser has finished parsing the DOM_ with all its inline resources. Assuming that everything critical has been processed a user might be able to start clicking around but this could be far from the truth.

Imagine that we forgot to add a JS file that is attaching events listener to a critical element above the fold. Then DOM interactive would not be a good indicator of interactivity. _DOM interactive_ would indicate that the page loaded at X time, but you'll click that critical element immediately after and, it won't work.

In other cases where your JS is fairly minimal and you have third-party libraries to for example load banners. Time to interactive will probably be more of a reflection of how long people wait for ads rather than other critical elements.

## Lab vs Field

### Time to Interactive: Lab Metric

It's good to mention that **Time to interactive** is a metric that can only be collected by running a synthetic test because of how it's measured. You need to explicitly run a performance audit to collect it in the browser and it is not a metric you can get from your real users' browser.

### DOM Interactive: Field Metric

There are some metrics that the browser collects fairly straight forward because of its nature. DOM interactive represents a specific event from the browser that is easily collectible from your page. That is why we have it present in the `performance.timing` browser API object. We can get that metric from our real users and send it to a centralized place to later analyze it.

## Conclusion

Time-to-interactive and DOM interactive are different metrics. Depending on your use case you might want Time to interactive. Do you want to analyze what your real users are experiencing? Then go with DOM interactive. Maybe you need both. The best way to know is to measure and see which metric gives you the information you need.

repository: neomaxzero/blog

repo_name: neomaxzero/blog


text:
# Block Helpers

Block helpers make it possible to define custom iterators and other functionality that can invoke the passed block with
a new context.

## Basic Blocks

For demonstration purposes, let's define a block helper that invokes the block as though no helper existed.

```handlebars
<div class="entry">
  <h1>{{title}}</h1>
  <div class="body">
    {{#noop}}{{body}}{{/noop}}
  </div>
</div>
```

The `noop` helper (short for "no operation") will receive an options hash. This options hash contains a function
(`options.fn`) that behaves like a normal compiled Handlebars template. Specifically, the function will take a context
and return a String.

```js
Handlebars.registerHelper("noop", function(options) {
  return options.fn(this);
});
```

Handlebars always invokes helpers with the current context as `this`, so you can invoke the block with `this` to
evaluate the block in the current context.

Any helpers defined in this manner will take precedence over fields defined in the context. To access a field that is
masked by a helper, a path reference may be used. In the example above a field named `noop` on the context object would
be referenced using:

```handlebars
{{./noop}}
```

## Basic Block Variation

To better illustrate the syntax, let's define another block helper that adds some markup to the wrapped text.

```handlebars
<div class="entry">
  <h1>{{title}}</h1>
  <div class="body">
    {{#bold}}{{body}}{{/bold}}
  </div>
</div>
```

The bold helper will add markup to make its text bold. As before, the function will take a context as input and return a
String.

```js
Handlebars.registerHelper("bold", function(options) {
  return new Handlebars.SafeString('<div class="mybold">' + options.fn(this) + "</div>");
});
```

## The `with` helper

The `with` helper demonstrates how to pass a parameter to your helper. When a helper is called with a parameter, it is
invoked with whatever context the template passed in.

```handlebars
<div class="entry">
  <h1>{{title}}</h1>
  {{#with story}}
    <div class="intro">{{{intro}}}</div>
    <div class="body">{{{body}}}</div>
  {{/with}}
</div>
```

You might find a helper like this useful if a section of your JSON object contains deeply nested properties, and you
want to avoid repeating the parent name. The above template could be useful with a JSON like:

```js
{
  title: "First Post",
  story: {
    intro: "Before the jump",
    body: "After the jump"
  }
}

```

::: v-pre

Implementing a helper like this is a lot like implementing the `noop` helper. Helpers can take parameters, and
parameters are evaluated just like expressions used directly inside `{{mustache}}` blocks.

:::

```js
Handlebars.registerHelper("with", function(context, options) {
  return options.fn(context);
});
```

Parameters are passed to helpers in the order that they are passed, followed by the options hash.

## Simple Iterators

A common use-case for block helpers is using them to define custom iterators. In fact, all Handlebars built-in helpers
are defined as regular Handlebars block helpers. Let's take a look at how the built-in `each` helper works.

```handlebars
<div class="entry">
  <h1>{{title}}</h1>
  {{#with story}}
    <div class="intro">{{{intro}}}</div>
    <div class="body">{{{body}}}</div>
  {{/with}}
</div>
<div class="comments">
  {{#each comments}}
    <div class="comment">
      <h2>{{subject}}</h2>
      {{{body}}}
    </div>
  {{/each}}
</div>
```

In this case, we want to invoke the block passed to `each` once for each element in the comments Array.

```js
Handlebars.registerHelper("each", function(context, options) {
  var ret = "";

  for (var i = 0, j = context.length; i < j; i++) {
    ret = ret + options.fn(context[i]);
  }

  return ret;
});
```

In this case, we iterate over the items in the passed parameter, invoking the block once with each item. As we iterate,
we build up a String result, and then return it.

This pattern can be used to implement more advanced iterators. For instance, let's create an iterator that creates a
`<ul>` wrapper, and wraps each resulting element in an `<li>.`

```handlebars
{{#list nav}}
  <a href="{{url}}">{{title}}</a>
{{/list}}
```

You would evaluate this template using something like this as the context:

```js
{
  nav: [
    { url: "http://www.yehudakatz.com", title: "Katz Got Your Tongue" },
    { url: "http://www.sproutcore.com/block", title: "SproutCore Blog" }
  ];
}
```

The helper is similar to the original `each` helper.

```js
Handlebars.registerHelper("list", function(context, options) {
  var ret = "<ul>";

  for (var i = 0, j = context.length; i < j; i++) {
    ret = ret + "<li>" + options.fn(context[i]) + "</li>";
  }

  return ret + "</ul>";
});
```

Using a library like underscore.js or SproutCore's runtime library could make this a bit prettier. For example, here's
what it might look like using SproutCore's runtime library:

```js
Handlebars.registerHelper("list", function(context, options) {
  return (
    "<ul>" +
    context
      .map(function(item) {
        return "<li>" + options.fn(item) + "</li>";
      })
      .join("\n") +
    "</ul>"
  );
});
```

## Conditionals

Another common use-case for block helpers is to evaluate conditional statements. As with the iterators, Handlebars'
built-in `if` and `unless` control structures are implemented as regular Handlebars helpers.

```handlebars
{{#if isActive}}
  <img src="star.gif" alt="Active">
{{/if}}
```

Control structures typically do not change the current context, instead they decide whether or not to invoke the block
based upon some variable.

```js
Handlebars.registerHelper("if", function(conditional, options) {
  if (conditional) {
    return options.fn(this);
  }
});
```

When writing a conditional, you will often want to make it possible for templates to provide a block of HTML that your
helper should insert if the conditional evaluates to false. Handlebars handles this problem by providing generic `else`
functionality to block helpers.

```handlebars
{{#if isActive}}
  <img src="star.gif" alt="Active">
{{else}}
  <img src="cry.gif" alt="Inactive">
{{/if}}
```

Handlebars provides the block for the `else` fragment as `options.inverse`. You do not need to check for the existence
of the else fragment: Handlebars will detect it automatically and register a "noop" function.

```js
Handlebars.registerHelper("if", function(conditional, options) {
  if (conditional) {
    return options.fn(this);
  } else {
    return options.inverse(this);
  }
});
```

Handlebars provides additional metadata to block helpers by attaching them as properties of the options hash. Keep
reading for more examples.

Conditionals may also be chained by including the subsequent helper call within the else mustache.

```handlebars
{{#if isActive}}
  <img src="star.gif" alt="Active">
{{else if isInactive}}
  <img src="cry.gif" alt="Inactive">
{{/if}}

```

It is not necessary to use the same helper in subsequent calls, the unless helper could be used in the else portion as
with any other helper. When the helper values are different, the closing mustache should match the opening helper name.

## Hash Arguments

Like regular helpers, block helpers can accept an optional Hash as its final argument. Let's revisit the `list` helper
and make it possible for us to add any number of optional attributes to the `<ul>` element we will create.

```handlebars
{{#list nav id="nav-bar" class="top"}}
  <a href="{{url}}">{{title}}</a>
{{/list}}
```

Handlebars provides the final hash as `options.hash`. This makes it easier to accept a variable number of parameters,
while also accepting an optional Hash. If the template provides no hash arguments, Handlebars will automatically pass an
empty object (`{}`), so you don't need to check for the existence of hash arguments.

```js
Handlebars.registerHelper("list", function(context, options) {
  var attrs = Object.keys(options.hash)
    .map(function(key) {
      return key + '="' + options.hash[key] + '"';
    })
    .join(" ");

  return (
    "<ul " +
    attrs +
    ">" +
    context
      .map(function(item) {
        return "<li>" + options.fn(item) + "</li>";
      })
      .join("\n") +
    "</ul>"
  );
});
```

Hash arguments provide a powerful way to offer a number of optional parameters to a block helper without the complexity
caused by positional arguments.

Block helpers can also inject private variables into their child templates. This can be useful to add extra information
that is not in the original context data.

For example, when iterating over a list, you may provide the current index as a private variable.

```handlebars
{{#list array}}
  {{@index}}. {{title}}
{{/list}}
```

```js
Handlebars.registerHelper("list", function(context, options) {
  var out = "<ul>",
    data;

  if (options.data) {
    data = Handlebars.createFrame(options.data);
  }

  for (var i = 0; i < context.length; i++) {
    if (data) {
      data.index = i;
    }

    out += "<li>" + options.fn(context[i], { data: data }) + "</li>";
  }

  out += "</ul>";
  return out;
});
```

Private variables provided via the `data` option are available in all descendent scopes.

Private variables defined in parent scopes may be accessed via pathed queries. To access the `index` field of the parent
iterator<EMAIL_ADDRESS>may be used.

Make sure you create a new data frame in each helper that assigns its own data. Otherwise, downstream helpers might
unexpectedly mutate upstream variables.

Also ensure that the `data` field is defined prior to attempting to interact with an existing data object. The private
variable behavior is conditionally compiled and some templates might not create this field.

## Block Parameters

New in Handlebars 3.0, it's possible to receive named parameters from supporting helpers.

```handlebars
{{#each users as |user userId|}}
  Id: {{userId}} Name: {{user.name}}
{{/each}}
```

In this particular example, `user` will have the same value as the current context and `userId` will have the index
value for the iteration.

This allows for nested helpers to avoid name conflicts that can occur with private variables.

```handlebars
{{#each users as |user userId|}}
  {{#each user.book as |book bookId|}}
    User Id: {{userId}} Book Id: {{bookId}}
  {{/each}}
{{/each}}
```

A number of [builtin helpers](builtin-helpers.html) support block parameters and any custom helper may provide them
through the `blockParams` options field.

Helpers can determine the number of block parameters referenced by the template via the `options.fn.blockParams` field,
which is an integer count. This value represents the number of block parameters that could be referenced by the child
template. Parameters beyond this count will never be referenced and can safely be omitted by the helper if desired. This
is optional and any additional parameters passed to the template will be silently ignored.

## Raw Blocks

Raw blocks are available for templates needing to handle unprocessed mustache blocks.

<ExamplePart examplePage="/examples/raw-blocks.md" show="template"/>

```handlebars
{{{{raw-helper}}}}
  {{bar}}
{{{{/raw-helper}}}}
```

will execute the helper raw-helper without interpreting the content.

```js
Handlebars.registerHelper("raw-helper", function(options) {
  return options.fn();
});
```

will render

```
{{bar}}
```

repository: handlebars-lang/docs

repo_name: handlebars-lang/docs