src/components/service/cameraSwitchService.ts
IHuddlyService class implementation for sdk consumers running on a Windows host machine. The service can be used to switch which huddly network camera is used to stream on the host machine. All the functionality of this service is described in the proto file from @huddly/camera-switch npm package with the name service.proto
IHuddlyService
Properties |
Methods |
constructor(opts?: IServiceOpts)
|
||||||||
|
Creates a new instance of CameraSwitchService and initializes the necessary class attributes
Parameters :
|
| grpcClient |
Type : HuddlyCameraServiceClient
|
|
Service client derived from the proto file |
| options |
Type : IServiceOpts
|
|
Service options for initializing and seting up the service communication |
| allowUserPtz |
allowUserPtz()
|
|
Update the user ptz setting on the huddly camera service to allow user ptz.
Returns :
Promise<void>
Promise |
| blokUserPtz |
blokUserPtz()
|
|
Update the user ptz setting on the huddly camera service to block user ptz.
Returns :
Promise<void>
Promise |
| close |
close()
|
|
Close grpc connection with the service gprc server. otherwise.
Returns :
Promise<void>
A promise that resolves if closing the connection is successful or rejects otherwise. |
| init |
init()
|
|
Connect to the service gprc server or rejects if not.
Returns :
Promise<void>
A promise that completes when the init is successful or rejects if not. |
| scheduleFwUpdateAll |
scheduleFwUpdateAll()
|
|
Schedule an immediate firmware upgrade on all the cameras available to the huddly camera service.
Returns :
Promise<FwUpdateScheduleStatus>
An object representing the status of the grpc request which contains the message and a list of affected cameras |
| serviceCameraGetter | ||||||||
serviceCameraGetter(action: ServiceCameraActions)
|
||||||||
|
Helper function for calling a getter command on the service grpc server. Using the parameter "action" to determine which specific getter to invoke. the service grpc seerver otherwise.
Parameters :
Returns :
Promise<CameraInfo>
A promise that resolves if the getter execution is successful or rejects otherwise. |
| serviceCameraSetter | ||||||||||||
serviceCameraSetter(action: ServiceCameraActions, camInfo: CameraInfo)
|
||||||||||||
|
Helper function for calling a setter command on the service grpc server. Using the parameter "action" to determine which specific setter to invoke. the service gprc server when calling the service gprc setter command otherwise.
Parameters :
Returns :
Promise<void>
A promse that resolves if the setter execution is successful or rejects otherwise. |
| setActiveCamera | ||||||||
setActiveCamera(camInfo: CameraInfoWrite)
|
||||||||
|
Set active camear on the huddly camera service. Note: this action is not boot persistent. when setting the activve camera on the service otherwise.
Parameters :
Returns :
Promise<void>
A promise that resolves if the active camera is set successfully or rejects otherwise. |
| setDefaultCamera | ||||||||
setDefaultCamera(camInfo: CameraInfoWrite)
|
||||||||
|
Set default camera on the huddly camera service. Note: this action is boot persistent. when setting the default camera on the service otherwise.
Parameters :
Returns :
Promise<void>
A promise that resolves if default camera is set successfully or rejects otherwise. |
| setFwUpdateSchedule | ||||||||
setFwUpdateSchedule(newSchedule: FwUpdateSchedule)
|
||||||||
|
Reconfigure firmware update scheduler on the huddly camera service.
Parameters :
Returns :
Promise<FwUpdateScheduleStatus>
An object representing the status of the grpc request which contains the message and a list of affected cameras |
| setUserPtz | ||||||||
setUserPtz(isAllowed: boolean)
|
||||||||
|
Set user pan tilt zoom control setting on the huddly camera service. This feature makes sure you allow or block custom user ptz to the camera comming from third party applications such as Windows Camera App, Zoom, Meet etc. allow or block incoming user ptz actions from third part apps. otherwise.
Parameters :
Returns :
Promise<void>
A promise that resolves if the setting was changed successfully or rejects otherwise. |
With version v0.6.0 we added support for Huddly IP Cameras on the SDK and with that a new feature exclusively on windows. This new feature allows you to switch the stream between different Huddly IP cameras used on various windows streaming applications (ex. windows camera app).
This feature can be useful in a multi-cam scenario where you have more than one Huddly IP camera set up on your meeting room and want to use the sdk to control which camera is used to stream on your zoom, google meet or microsoft teams meeting.
The pre-requisites for using this feature are:
In order to be able to tell the service to switch from one camera to another, you need to be able to list all available cameras on your network and find their corresponding ip addresses. Here is a code snippet that helps you find the list of cameras:
const HuddlyDeviceApiIp = require('@huddly/device-api-ip').default;
const HuddlyDeviceApiIUsb = require('@huddly/device-api-usb').default;
const HuddlySdk = require('@huddly/sdk').default;
const { HUDDLY_L1_PID } = require('@huddly/sdk/lib/src/components/device/factory').default;
const ipApi = new HuddlyDeviceApiIp();
const usbApi = new HuddlyDeviceApiIUsb();
// Create an instance of the SDK
const sdk = new HuddlySdk([usbApi, ipApi], [usbApi, ipApi]);
const applicationTeardown = () => {
process.exit();
}
const searchTime = 30; // seconds
const cameraList = [];
sdk.on('ATTACH', (huddlyDevice) => {
if (huddlyDevice.pid == HUDDLY_L1_PID) {
console.log(`Found [${huddlyDevice.productName}] device!`)
huddlyDevice.getInfo()
.then(info => {
cameraList.push(info)
})
.catch((e) => {
console.error(`Unable to get camera info from [${huddlyDevice.productName}]`)
console.trace(e);
}).finally(_ => {
huddlyDevice.closeConnection();
});
}
});
setTimeout(() => {
console.group('Camera List')
console.log(cameraList)
console.groupEnd();
applicationTeardown();
}, searchTime * 1000)
sdk.init();
Running the code snippet above should give you the following result
Found [Huddly L1] device!
Found [Huddly L1] device!
Camera List
[
{
name: 'L1',
mac: '90:E2:FC:90:12:EC',
ipv4: '<IP_ADDRESS>',
serialNumber: '12101A0029',
modelName: '810-00011-MBLK',
manufacturer: 'Huddly',
productId: 1001,
version: '1.2.6-4302.12+sha.cc52293',
uptime: 22417.75,
slot: 'B'
},
{
name: 'L1',
mac: '90:E2:FC:90:12:ED',
ipv4: '<IP_ADDRESS>',
serialNumber: '12101A0039',
modelName: '810-00011-MWHT',
manufacturer: 'Huddly',
productId: 1001,
version: '1.2.6-4302.12+sha.cc52293',
uptime: 344.75,
slot: 'B'
}
]
Now that you have the information about all the connected Huddly IP cameras on your network, you can use the service to figure out which camera is picked by default by the Huddly IP camera driver, switch to a different camera, set the default camera etc.
The code snipped below will illustrate the camera switch service funcionalities:
// Import SDK
const HuddlySdk = require('@huddly/sdk').default;
// Get a new camera switch service instance
const cameraSwitchService = await HuddlySdk.getService();
// Get the active camera currently picked by the driver
const activeCameraObj = await cameraSwitchService.getActiveCamera();
// Get the default camera currently set for the driver (can be empty if not set before)
const defaultCameraObj = await cameraSwitchService.getDefaultCamera();
// Switch between different cameras
const huddlyIpCamera1 = {
name: "L1",
ip: '<IP_ADDRESS>'
}
const huddlyIpCamera2 = {
name: "L1",
ip: '<IP_ADDRESS>'
}
// Switch to camera1
await cameraSwitchService.setActiveCamera(huddlyIpCamera1);
// Switch to camera2
await cameraSwitchService.setActiveCamera(huddlyIpCamera2);
// Make camera2 default pick for the driver (persistent across boot)
await cameraSwitchService.setDefaultCamera(huddlyIpCamera2);
import IHuddlyService from '@huddly/sdk-interfaces/lib/interfaces/IHuddlyService';
import IServiceOpts from '@huddly/sdk-interfaces/lib/interfaces/IServiceOpts';
import {
CameraInfo,
CameraPairingState,
FwUpdateSchedule,
FwUpdateScheduleStatus,
CameraInfoWrite,
} from '@huddly/sdk-interfaces/lib/interfaces/ICameraSwitchModels';
import Logger from '@huddly/sdk-interfaces/lib/statics/Logger';
import * as switchservice from '@huddly/camera-switch-proto/lib/api/service_pb';
import { HuddlyCameraServiceClient } from '@huddly/camera-switch-proto/lib/api/service_grpc_pb';
import * as grpc from '@grpc/grpc-js';
import { Empty } from 'google-protobuf/google/protobuf/empty_pb';
/**
* Local enum describing service camera actions used to simplify api calls
* towards the service through GRPC
*/
export enum ServiceCameraActions {
ACTIVE = 0,
DEFAULT = 1,
}
/**
* @export
*
* IHuddlyService class implementation for sdk consumers running on a Windows host machine. The service can be used
* to switch which huddly network camera is used to stream on the host machine. All the functionality of this
* service is described in the proto file from @huddly/camera-switch npm package with the name service.proto
*
* @class CameraSwitchService
* @implements {IHuddlyService}
*/
export default class CameraSwitchService implements IHuddlyService {
/**
* Service options for initializing and seting up the service communication
* @type {IServiceOpts}
* @memberof CameraSwitchService
*/
options: IServiceOpts;
/**
* Service client derived from the proto file
* @type {HuddlyCameraServiceClient}
* @memberof CameraSwitchService
*/
grpcClient: HuddlyCameraServiceClient;
/**
* @ignore
* @type {number}
* @memberof CameraSwitchService
*/
private readonly GRPC_DEFAULT_CONNECT_TIMEOUT: number = 1; // Seconds
/**
* @ignore
* @type {number}
* @memberof CameraSwitchService
*/
private readonly GRPC_PORT: number = 30051;
/**
* Creates a new instance of CameraSwitchService and initializes the necessary class attributes
* @param {IServiceOpts} opts? Service options for initializing and setting up the service communication
*/
constructor(opts?: IServiceOpts) {
this.options = opts;
}
/**
* Connect to the service gprc server
* @returns A promise that completes when the init is successful
* or rejects if not.
*/
init(): Promise<void> {
Logger.debug('Initializing Windows Ip Camera Service!', CameraSwitchService.name);
const deadline = new Date();
deadline.setSeconds(
deadline.getSeconds() + (this.options.connectionDeadline || this.GRPC_DEFAULT_CONNECT_TIMEOUT)
);
this.grpcClient = new HuddlyCameraServiceClient(
`localhost:${this.GRPC_PORT}`,
this.options.credentials || grpc.credentials.createInsecure()
);
return new Promise<void>((resolve, reject) =>
this.grpcClient.waitForReady(deadline, (error) => {
if (error) {
Logger.error(
`Connection failed with GPRC server on ACE!`,
error,
CameraSwitchService.name
);
reject(error);
} else {
Logger.debug(`Connection established`, CameraSwitchService.name);
resolve();
}
})
);
}
/**
* Helper function for calling a setter command on the service grpc server. Using the
* parameter "action" to determine which specific setter to invoke.
* @param {ServiceCameraActions} action Determine which setter should be called on
* the service gprc server
* @param {CameraInfo} camInfo The camera information required to send in as data
* when calling the service gprc setter command
* @returns A promse that resolves if the setter execution is successful or rejects
* otherwise.
*/
serviceCameraSetter(action: ServiceCameraActions, camInfo: CameraInfo): Promise<void> {
const serviceCamInfo: switchservice.CameraInfoWrite = new switchservice.CameraInfoWrite();
serviceCamInfo.setName(camInfo.name);
serviceCamInfo.setIp(camInfo.ip);
const setterActionStr: string = Object.keys(ServiceCameraActions).find(
(key) => ServiceCameraActions[key] === action
);
return new Promise((resolve, reject) => {
const setterCallback = (err: grpc.ServiceError) => {
if (err) {
Logger.error(
`Unable to set ${setterActionStr} camera on service. Error: ${err.details}`,
err.stack,
CameraSwitchService.name
);
reject(err.details);
return;
}
resolve();
};
switch (action) {
case ServiceCameraActions.ACTIVE:
this.grpcClient.setActiveCamera(serviceCamInfo, setterCallback);
break;
case ServiceCameraActions.DEFAULT:
this.grpcClient.setDefaultCamera(serviceCamInfo, setterCallback);
break;
default:
throw new Error(`Unknown service camera action: ${setterActionStr}`);
}
});
}
/**
* Helper function for calling a getter command on the service grpc server. Using the
* parameter "action" to determine which specific getter to invoke.
* @param {ServiceCameraActions} action Determine which getter should be called on
* the service grpc seerver
* @returns A promise that resolves if the getter execution is successful or rejects
* otherwise.
*/
serviceCameraGetter(action: ServiceCameraActions): Promise<CameraInfo> {
const getterActionStr: string = Object.keys(ServiceCameraActions).find(
(key) => ServiceCameraActions[key] === action
);
return new Promise((resolve, reject) => {
const getterCallback = (err: grpc.ServiceError, device: switchservice.CameraInfo) => {
if (err) {
Logger.error(
`Unable to get ${getterActionStr} camera from service. Error: ${err.details}`,
err.stack,
CameraSwitchService.name
);
reject(err.details);
return;
}
resolve({
ip: device.getIp(),
name: device.getName(),
version: device.getVersion(),
version_state: this.versionStateToString(device),
pairing_state: this.pairingStateToStringArray(device.getPairingStatesList()),
});
};
switch (action) {
case ServiceCameraActions.ACTIVE:
this.grpcClient.getActiveCamera(new Empty(), getterCallback);
break;
case ServiceCameraActions.DEFAULT:
this.grpcClient.getDefaultCamera(new Empty(), getterCallback);
break;
default:
throw new Error(`Unknown service camera action: ${getterActionStr}`);
}
});
}
/**
* Set default camera on the huddly camera service. Note: this action is boot persistent.
* @param {CameraInfo} camInfo The camera information required to send in as data
* when setting the default camera on the service
* @returns A promise that resolves if default camera is set successfully or rejects
* otherwise.
*/
setDefaultCamera(camInfo: CameraInfoWrite): Promise<void> {
return this.serviceCameraSetter(ServiceCameraActions.DEFAULT, camInfo);
}
/**
* Get default camera from the huddly camera service.
* @returns A promise which contains data of type `CamerInfo` detailing the information
* about the current default camera on the huddly camera service.
*/
getDefaultCamera(): Promise<CameraInfo> {
return this.serviceCameraGetter(ServiceCameraActions.DEFAULT);
}
/**
* Set active camear on the huddly camera service. Note: this action is not boot persistent.
* @param {CameraInfo} camInfo The camera information reqyuired to send in as data
* when setting the activve camera on the service
* @returns A promise that resolves if the active camera is set successfully or rejects
* otherwise.
*/
setActiveCamera(camInfo: CameraInfoWrite): Promise<void> {
return this.serviceCameraSetter(ServiceCameraActions.ACTIVE, camInfo);
}
/**
* Get active camera from the huddly camera service.
* @returns A promise which contains data of type `CameraInfo` detailing the information
* about the current active camera on the huddly camera service.
*/
getActiveCamera(): Promise<CameraInfo> {
return this.serviceCameraGetter(ServiceCameraActions.ACTIVE);
}
/**
* Set user pan tilt zoom control setting on the huddly camera service. This feature
* makes sure you allow or block custom user ptz to the camera comming from third party
* applications such as Windows Camera App, Zoom, Meet etc.
* @param {boolean} isAllowed A boolean parameter specifying whether the service should
* allow or block incoming user ptz actions from third part apps.
* @returns A promise that resolves if the setting was changed successfully or rejects
* otherwise.
*/
setUserPtz(isAllowed: boolean): Promise<void> {
const allowed = new switchservice.UserPtz();
allowed.setEnabled(isAllowed);
return new Promise((resolve, reject) => {
this.grpcClient.setUserPTZ(allowed, (err: grpc.ServiceError) => {
if (err) {
Logger.error(
`Unable to set user ptz on service. Error: ${err.details}`,
err.stack,
CameraSwitchService.name
);
reject(err.details);
return;
}
resolve();
});
});
}
/**
* Check if the user ptz is allowed on the huddly camera service.
* @returns A promise which after completion it contains information if
* user ptz is allowed or not. Rejects if retreiving the setting fails.
*/
isUserPtzAllowed(): Promise<boolean> {
return new Promise((resolve, reject) => {
this.grpcClient.getUserPTZ(
new Empty(),
(err: grpc.ServiceError, isAllowed: switchservice.UserPtz) => {
if (err) {
Logger.error(
`Unable to get information whether user ptz is allowed or not on the service. Error: ${err.details}`,
err.stack,
CameraSwitchService.name
);
reject(err.details);
return;
}
resolve(isAllowed.getEnabled());
}
);
});
}
/**
* Update the user ptz setting on the huddly camera service to allow user ptz.
* @returns Promise
*/
allowUserPtz(): Promise<void> {
return this.setUserPtz(true);
}
/**
* Update the user ptz setting on the huddly camera service to block user ptz.
* @returns Promise
*/
blokUserPtz(): Promise<void> {
return this.setUserPtz(false);
}
/**
* @ignore
* Helper function for converting CameraPairingState enum values into array of enum keys
* @param pairingStateList List of proto CameraPairingState values
* @returns A string array representing the keys for the different Pairing states of the camera
*/
pairingStateToStringArray(
pairingStateList: Array<
switchservice.CameraPairingStateMap[keyof switchservice.CameraPairingStateMap]
>
): Array<string> {
const pairingStates: Array<string> = [];
pairingStateList.forEach((state) => {
// Check for unknown pairing states
if (CameraPairingState[state] == undefined) {
// Check for duplicates
if (
!pairingStates.includes(
CameraPairingState[switchservice.CameraPairingState.UNKNOWNPAIRINGSTATE]
)
) {
pairingStates.push(CameraPairingState[CameraPairingState.UnknownPairingState]);
}
} else {
// Check for duplicates
if (!pairingStates.includes(CameraPairingState[state])) {
pairingStates.push(CameraPairingState[state]);
}
}
});
return pairingStates;
}
/**
* @ignore
* Helper function for converting device VersionState into a string representation
* @param device Service CameraInfo instance used to extract the version state object from
* @returns A string representation of the device version state
*/
versionStateToString(device: switchservice.CameraInfo): string {
return Object.keys(switchservice.VersionState).find(
(state) => switchservice.VersionState[state] == device.getVersionState()
);
}
/**
* @ignore
* Helper function for converting list of `@huddly/camera-switch-proto/CameraInfo` into local `CameraInfo` list representation.
* @param cameraList List instance of `@huddly/camera-switch-proto/CameraInfo` objects to be converted into local `CameraInfo` list representation
* @returns A list of local `CameraInfo` objects converted from `@huddly/camera-switch-proto/CameraInfo`
*/
protoCameraInfoListToLocalCameraInfoList(
cameraList: Array<switchservice.CameraInfo>
): Array<CameraInfo> {
const newConveredCameraList: Array<CameraInfo> = new Array<CameraInfo>();
cameraList.forEach((device) => {
newConveredCameraList.push({
ip: device.getIp(),
name: device.getName(),
version: device.getVersion(),
version_state: this.versionStateToString(device),
pairing_state: this.pairingStateToStringArray(device.getPairingStatesList()),
});
});
return newConveredCameraList;
}
/**
* Get a list of all available cameras that have been discovered and are ready to be used on the huddly camera service.
* @returns A list of all available cameras on the service.
*/
getAvailableCameras(): Promise<Array<CameraInfo>> {
return new Promise((resolve, reject) => {
this.grpcClient.getAvailableCameras(
new Empty(),
(err: grpc.ServiceError, availableCameras: switchservice.AvailableCameras) => {
if (err) {
Logger.error(
`Unable to get available cameras from the service. Error: ${err.details}`,
err.stack,
CameraSwitchService.name
);
reject(err.details);
return;
}
const resolveList: Array<CameraInfo> = this.protoCameraInfoListToLocalCameraInfoList(
availableCameras.getCameraListList()
);
resolve(resolveList);
}
);
});
}
/**
* @ignore
* Helper function for converting comma separated camera pairing state keys into proto compatible CameraPairingStateMap used
* when sending grpc requests to the service grpc server.
* @param states A comma separated string of CameraPairingState keys
* @returns A list of CameraPairingState objects represented as `repeated CameraPairingState` type on the service proto messages
*/
pairingStateKeysToValues(
states: string
): Array<switchservice.CameraPairingStateMap[keyof switchservice.CameraPairingStateMap]> {
const pairStateEnumValues: Array<
switchservice.CameraPairingStateMap[keyof switchservice.CameraPairingStateMap]
> = [];
const allowedCameraPairingStates: string[] = Object.keys(CameraPairingState).filter(
(x) => !(parseInt(x) >= 0)
);
states.split(',').forEach((state) => {
if (allowedCameraPairingStates.includes(state)) {
// Avoid adding duplicates
if (!pairStateEnumValues.includes(CameraPairingState[state])) {
pairStateEnumValues.push(CameraPairingState[state]);
}
} else {
throw new Error(
`Unknown CameraPairingState [${state}]! Allowed States: ${allowedCameraPairingStates}`
);
}
});
return pairStateEnumValues;
}
/**
* Reconfigure firmware update scheduler on the huddly camera service.
* @param newSchedule New firmware update schedule to be applied to the windows service
* @returns An object representing the status of the grpc request which contains the message and a list of affected cameras
*/
setFwUpdateSchedule(newSchedule: FwUpdateSchedule): Promise<FwUpdateScheduleStatus> {
const request: switchservice.FwUpdateSchedule = new switchservice.FwUpdateSchedule();
request.setDaysOfWeek(newSchedule.daysOfWeek);
request.setHourOfDay(newSchedule.hour);
request.setStartDelayMaxSeconds(newSchedule.maxStartDelay);
request.setValidPairingStatesList(
this.pairingStateKeysToValues(newSchedule.validPairingStates)
);
request.setDisabled(newSchedule.disabled == undefined ? false : newSchedule.disabled);
return new Promise((resolve, reject) => {
this.grpcClient.setFwUpdateSchedule(
request,
(err: grpc.ServiceError, status: switchservice.FwUpdateScheduleStatus) => {
if (err) {
Logger.error(
`Unable to set new fw update schedule. Error: ${err.details}`,
err.stack,
CameraSwitchService.name
);
reject(err.details);
return;
}
if (status.getCode() != switchservice.FwUpdateScheduleStatusCodes.SUCCESS) {
Logger.error(
`Server reported error when setting new fw update schedule`,
undefined,
CameraSwitchService.name
);
reject(status.getMessage());
return;
}
const affectedCameras: Array<CameraInfo> = this.protoCameraInfoListToLocalCameraInfoList(
status.getAffectedCamerasList()
);
resolve({
message: status.getMessage(),
affectedCameras,
});
}
);
});
}
/**
* Retrieve the current configured fw update schedule from the huddly camera service.
* @returns A FwUpdateSchedule object containing all the information about the current fw schedule on the service
*/
getFwUpdateSchedule(): Promise<FwUpdateSchedule> {
return new Promise((resolve, reject) => {
this.grpcClient.getFwUpdateSchedule(
new Empty(),
(err: grpc.ServiceError, schedule: switchservice.FwUpdateSchedule) => {
if (err) {
Logger.error(
`Unable to retrieve fw update schedule. Error: ${err.details}`,
err.stack,
CameraSwitchService.name
);
reject(err.details);
return;
}
resolve({
daysOfWeek: schedule.getDaysOfWeek(),
validPairingStates: this.pairingStateToStringArray(
schedule.getValidPairingStatesList()
).join(','),
disabled: schedule.getDisabled(),
hour: schedule.getHourOfDay(),
maxStartDelay: schedule.getStartDelayMaxSeconds(),
});
}
);
});
}
/**
* Schedule an immediate firmware upgrade for the given camera on the huddly camera service. Given that the camera is available
* on the service.
* @param cameraToUpgrade Camera info representing the camera to be upgraded by the service.
* @returns An object representing the status of the grpc request which contains the message and a list of affected cameras
*/
scheduleFwUpdate(cameraToUpgrade: CameraInfoWrite): Promise<FwUpdateScheduleStatus> {
const request: switchservice.CameraInfoWrite = new switchservice.CameraInfoWrite();
request.setIp(cameraToUpgrade.ip);
request.setName(cameraToUpgrade.name);
return new Promise((resolve, reject) => {
this.grpcClient.scheduleFwUpdate(
request,
(err: grpc.ServiceError, status: switchservice.FwUpdateScheduleStatus) => {
if (err) {
Logger.error(
`Unable to schedule upgrade for camera (Ip: ${cameraToUpgrade.ip}, Name: ${cameraToUpgrade.name})`,
err.stack,
CameraSwitchService.name
);
reject(err.details);
return;
}
if (status.getCode() != switchservice.FwUpdateScheduleStatusCodes.SUCCESS) {
Logger.error(
`Unable to schedule upgrade for camera (Ip: ${cameraToUpgrade.ip}, Name: ${cameraToUpgrade.name})`,
undefined,
CameraSwitchService.name
);
reject(status.getMessage());
return;
}
const affectedCameras: Array<CameraInfo> = this.protoCameraInfoListToLocalCameraInfoList(
status.getAffectedCamerasList()
);
resolve({
message: status.getMessage(),
affectedCameras,
});
}
);
});
}
/**
* Schedule an immediate firmware upgrade on all the cameras available to the huddly camera service.
* @returns An object representing the status of the grpc request which contains the message and a list of affected cameras
*/
scheduleFwUpdateAll(): Promise<FwUpdateScheduleStatus> {
return new Promise((resolve, reject) => {
this.grpcClient.scheduleFwUpdateAll(
new Empty(),
(err: grpc.ServiceError, status: switchservice.FwUpdateScheduleStatus) => {
if (err) {
Logger.error(
`Unable to schedule fw update on all connected cameras! Error: ${err.details}`,
err.stack,
CameraSwitchService.name
);
reject(err.details);
return;
}
if (status.getCode() != switchservice.FwUpdateScheduleStatusCodes.SUCCESS) {
Logger.error(
'Unable to schedule fw update on all connected cameras!',
undefined,
CameraSwitchService.name
);
reject(status.getMessage());
return;
}
const affectedCameras: Array<CameraInfo> = this.protoCameraInfoListToLocalCameraInfoList(
status.getAffectedCamerasList()
);
resolve({
message: status.getMessage(),
affectedCameras,
});
}
);
});
}
/**
* Close grpc connection with the service gprc server.
* @returns A promise that resolves if closing the connection is successful or rejects
* otherwise.
*/
close(): Promise<void> {
if (this.grpcClient) {
this.grpcClient.close();
this.grpcClient = undefined;
}
return Promise.resolve();
}
}


a full stack developer and software engineer
I am a software engineer that specializes in web development. However, it is a hobby for me to write Android applications for fun.
Over 15 years of experience in several different programming technologies
Over 8 years of being a professional full-stack developer
Several projects that required content management and collaboration
Approximately 64k downloads of my android application
Amanda and Jacob Smith's Wedding Page.
Jacob and Amanda are two dear friends of mine and I created this page as an engagement gift
to them.
I am a Software Engineer that lives in Gastonia, NC (near Charlotte, NC). My passion is in all kinds of computer programming, such as web development, scripting, desktop/server applications, IoT, and even mobile applications. I'm also an Android enthusiast and avid golfer.
I started web development when I was still in high school because I originally wanted to start making a hobby website with some friends. That eventually led to my realization for my love to code. I spent several years learning the basics and playing around with some server sides languages such as PHP. By the end of college, I had built two different hobby websites for fun. It has been several years now, but I am skilled in several different languages and still learning more every day!
| HTML | |
| CSS | |
| Javascript | |
| Bootstrap 3 | |
| Object Oriented Programming | |
| Model-View-Controller (MVC) | |
| Network Security | |
| Windows Server / .NET Hosting | |
| Visual Studio | |
| jQuery | |
| SQL Server | |
| MySQL |
| Team Foundation Server | |
| Java | |
| GIT | |
| Telerik UI Tools | |
| GitHub | |
| Eclipse | |
| SharePoint | |
| JetBrain IDE's (Intellij, PHPStorm, etc) | |
| Android Development | |
| Python | |
| PHP | |
| Rockwell Automation FactoryTalk |
To see a collection of my work, please visit my blog's project page at DotNetEvolved Projects
Use one of the social media platforms below to reach out to me!


@* * Copyright 2023 HM Revenue & Customs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *@ @import config.ApplicationConfig @import uk.gov.hmrc.govukfrontend.views.html.components.implicits._ @import uk.gov.hmrc.govukfrontend.views.html.components._ @import views.html.components.link @this(govukButton: GovukButton, mainLayout: views.html.mainLayout) @(backLink: String)(implicit request: Request[_], messages: Messages, config: ApplicationConfig) @mainLayout( pageTitle = messages("propertyRepresentation.start.title"), backUri = Some(backLink), ) {
@messages("propertyRepresentation.start.theyCan.1")
@messages("propertyRepresentation.start.theyCan.2")
@messages("propertyRepresentation.start.youCan.1")


Contact and info about the organisation NIE-INE | NATIONAL INFRASTRUCTURE FOR EDITIONS | A swiss-wide organisation for the infrastructure of editions: https://www.nie-ine.ch/
Powered by FEE, mandated by swissuniversities
nieOS
Get it up and running for development
Clone nieOS
git clone https://github.com/nie-ine/nieOS.git
cd nieOS
1. Create MongoDB instance:
Alternative 1: Create your own MongoDB instance:
- Create a sandbox on Mongodb, choose a free instance.
- In this sandbox, add your IP to the whitelist
- Get the server-connect string, similiar to this:
<EMAIL_ADDRESS>via klick on Connect, klick on connect your application, klick one nodejs
2. Connect nieOS to MongoDB:
- Create a folder .settings
- In the folder settings, create the file mongodbServer.js Your file should look similiar to the following:
const mongodbServer =<EMAIL_ADDRESS>module.exports = {
mongodbServer: mongodbServer
};
- another file in this folder should be mailDetails, where you can put the information for your email - server, it should look like the following:
const emailAdress = '<your Email Address>';
const pw = '<your password>';
const recipient = '<default recipient if there is no other one defined>';
const type = '<type of your mail server>';
module.exports = {
emailAdress: emailAdress,
pw: pw,
recipient: recipient,
type: type
};
- another file is nieOsServer.js:
const nieOSServer = 'http://localhost:4200';
module.exports = {
nieOSServer: nieOSServer
};
const salt = 'your_secret_that_should_be_very_long';
module.exports = {
salt: salt
};
3. Start Angular and Node.js
4. Start node.js
npm run start:server
Run in Docker container
run docker-compose up
Deployment procedure
- locally run
docker built -t mean .
- locally try
docker-compose up
If everything works as expected, push the mean - image to dockerhub (once tag it as with a version, once tag it with latest) and pull it on your server.
Running unit tests
Run ng test
to execute the unit tests via Karma.
Development advice/ helping notes
Extend nieOS models / move them from localstorage to mongodb
- create an interface, like in shared/nieOS/mongodb/action/action.ts
- in backend/models add action.js for mongoose
- in backend/routes add .js to post / update etc
- add routes in app.js
- create new service for mongodb in frontend, like mongodbAction.service.ts
- test route in backend with console.log (without backend operations at first, bc it's easier.)
- add mongoose Schema, instantiate it in backend/routes and assign req.body to mongoose object
- save data to the database (ref tutorial 53)
- check if it worked with mongo shell, again in 53
- Fetch data from database, 54. Mongoose - docs tells more details on how to narrow fetching the data. Example again in backend/routes/action.js
- Map _id from mongodb to id in frontent, like in dashboard.component.ts onInit()
- integrate delete and update functions


Josephu's Problem is a well known mathematical problem that involves counting and divergent series. Every second position of a circle divided evenly by N is removed. What is the last remaining position?
You didn't get any of that ? Oh, don't worry. We solved it for you!
SCROLL DOWN
Let's say you and some other people owe money to very shady mafia of mathematicians. They, for no particular reason, decide to spare one of you.So, everyone will be put around in a circle and they will start shooting every second alive person until there is only one left standing. If you want to survive, you have to know what position you need to take in order to not get shot. How do you do that?
Being very good with numbers, and with an unbreakable will to survive, you start running different scenarios through your head. If they bring only two people, it is obvious that the first one would be spared. If they bring three people, the third one will. If they bring 4, it would be the first again.  At least you have nothing to distract you along the way, hum?
Anyway, going throught all those different scenarios, you start to realize there is a pattern:
The result series (right hand side) resets at every power of 2. It makes sense, since every second person is being shot. But hey, that is not all. This is a very simple series, aside from the eventual reset at powers of 2. You just have to add two to the previous value for every new person that arrives at this mathematical russian roullet.
If you need to find where you should stand if 14 other people decided to make the same life choices as you did, you can reason that it is equal to the number of people in this hellish circle minus the closest lower power of two: 15-8 = 7. Now, that gives you the number of steps in the series that adds two to every step: So 7*2 = 14. Since you start at 1, you need to add 1 to this result. So 14+1 = 15. You rejoice yourself in the certainty of survival.
Let's recap.  I have to say, you have outdone yourself. Congratulations.


| Name | Address | IEEE | Command |
|---|---|---|---|
| {{a.NAME}} | {{a.SHORT_ADDR}} | {{a.IEEE_ADDR}} |
Add device to ZigBee NetworkDelete device in ZigBee Network |


- setA(int) - Method in class com.lib.pygmy.util.Color
-
- setB(int) - Method in class com.lib.pygmy.util.Color
-
- setBitmap(Bitmap) - Method in interface com.lib.pygmy.GameEntity
-
Sets the inflated bitmap of this instance
- setBitmap(Bitmap) - Method in class com.lib.pygmy.PygmyGameEntity
-
Sets the inflated bitmap of this instance
- setBoardType(int) - Method in interface com.lib.pygmy.GameLevel
-
Sets the level's board type
- setBoardType(int) - Method in class com.lib.pygmy.PygmyGameLevel
-
Sets the level's board type
- setColor(Paint) - Method in class com.lib.pygmy.Tile
-
Sets the tile's color
- setColors(List<Color>) - Method in interface com.lib.pygmy.GameLevel
-
Sets the tile colors of the level's board
- setColors(List<Color>) - Method in class com.lib.pygmy.PygmyGameLevel
-
Sets the tile colors of the level's board
- setCoordinates(int, int, int, int) - Method in class com.lib.pygmy.Tile
-
Sets the absolute position of the tile
- setCoordinates(int, int) - Method in class com.lib.pygmy.Tile
-
Sets the absolute position of the tile
- setCurrentLevel(GameLevel) - Method in class com.lib.pygmy.PygmyGameContext
-
- setCurrentPlayerId(String) - Method in class com.lib.pygmy.PygmyGameContext
-
- setCurrentTile(Tile) - Method in interface com.lib.pygmy.GameEntity
-
Sets the current tile occupied by this instance
- setCurrentTile(Tile) - Method in class com.lib.pygmy.PygmyGameEntity
-
Sets the current tile occupied by this instance
- setDestination(Point) - Method in interface com.lib.pygmy.base.Movable
-
- setDestination(Tile) - Method in class com.lib.pygmy.GameMove
-
Sets the entity's destination
- setDimensions(int, int) - Method in interface com.lib.pygmy.GameLevel
-
Sets the level's dimensions
- setDimensions(int, int) - Method in class com.lib.pygmy.PygmyGameLevel
-
Sets the level's dimensions
- setEntity(GameEntity) - Method in class com.lib.pygmy.GameMove
-
Sets the entity to move
- setG(int) - Method in class com.lib.pygmy.util.Color
-
- setGamePath(Activity, String) - Static method in class com.lib.pygmy.util.PygmyLoader
-
Updates the path of the next game to load.
- setLevels(List<GameLevel>) - Method in interface com.lib.pygmy.Game
-
Sets the game's levels
- setLevels(List<GameLevel>) - Method in class com.lib.pygmy.PygmyGame
-
Sets the game's levels
- setOverlapRules(OverlapRulesApplier) - Method in interface com.lib.pygmy.OverlapProcessor
-
- setOverlapRules(OverlapRulesApplier) - Method in class com.lib.pygmy.OverlapProcessorImpl
-
- setPlayerId(String) - Method in interface com.lib.pygmy.GameEntity
-
Sets the player ID associated to this instance
- setPlayerId(String) - Method in class com.lib.pygmy.PygmyGameEntity
-
Sets the player ID associated to this instance
- setPlayerIds(List<String>) - Method in interface com.lib.pygmy.Game
-
Sets the IDs of the participant players
- setPlayerIds(List<String>) - Method in class com.lib.pygmy.PygmyGame
-
Sets the IDs of the participant players
- setPlayers(List<String>) - Method in class com.lib.pygmy.PygmyGameContext
-
- setPosition(Point) - Method in class com.lib.pygmy.Tile
-
Sets the relative position of the tile
- setR(int) - Method in class com.lib.pygmy.util.Color
-
- setUniverse(GameUniverse) - Method in interface com.lib.pygmy.OverlapProcessor
-
- setUniverse(GameUniverse) - Method in class com.lib.pygmy.OverlapProcessorImpl
-
- setUniverse(GameUniverse) - Method in interface com.lib.pygmy.OverlapRulesApplier
-
Sets the managed universe by this instance
- setValue(T) - Method in class com.lib.pygmy.base.ObservableValue
-
- start() - Method in interface com.lib.pygmy.Game
-
Starts the game by running the first level
- start() - Method in interface com.lib.pygmy.GameLevel
-
Starts the level
- start() - Method in class com.lib.pygmy.PygmyGame
-
Starts the game by running the first level
- start() - Method in class com.lib.pygmy.PygmyGameLevel
-
Starts the level
- state - Variable in class com.lib.pygmy.util.TurnData
-


[1]
hope you find my review helpful to you.
[2]
hope you 'll find a tip to my budget and my needs but if you are.


Shop Now |
View in a Web Browser
Gold Sequin Sheer BlouseSize Medium Price: $7.00
Sequin drop neck dressSize Medium Price: $15.00
0 20XX All rights Reserved - Yourcompany. Is your inbox overflowing? Unsubscribe


{% extends "global/Page.html" %} {% load otree static %} {% block title %} Conclusion {% endblock %} {% block content %}
Thank you for your participation! You have earned a total of {{acc_profit}}, which is worth {{acc_dollar}}. Your total payoff, including your participation fee, would then be {{acc_final}}.
You may now leave! Please report your assigned ID to the experimenter and receive the money. If you have any questions after the experiment, please contact Botao Qin at<PHONE_NUMBER> or bqin@xjtu.edu.cn.


1 Load packages
library(tidyverse) # data wrangling
2 Motivation
In some sense, science is about estimating the effect sizes in a population, such as \(\mu\). In the most basic form, perhaps, the question is nothing more than whether \(\mu=0\) or not.
Given a population of limited size, we might be tempted to say, let’s measure all instances (such as individuals) of the population to come up wit the “real” \(\mu\). For concreteness, the population might consist of parts produced by some machine, or papers written by some scientists, which is the same for the question we are looking at now.
In this post, we will simulate the effect of sample sizes on population parameter estimates, in particular \(\mu\), but without of loss of generality, this applies to other type of population parameter in the same way. Of note, effect sizes can be converted from one to one other, such as \(r, OR, SMD, RR\), and the like.
3 True value of the parameter
Let’s decide on the true population parameter value. I argue that it is impossible, or at least unlikely, that the absolute value of this parameter is large. It it were large, we had no doubts about it. For instance, the effect size of water in the face of thirst is large. The effect of parachutes on falling speed is large. No need for estimating population parameter values.
For the sake of concreteness, I will speak of the “effectiveness of some medical intervention” in the following when I refer to the parameter value of \(\mu\).
On the other hand, if the value of the parameter is not large (in absolute terms), we arrive at the question whether the value is zero or not. I doubt that more precise values can be estimated in most practical cases. For example, to be confident that \(\mu=0.42\) rather than \(\mu=0.271\) (in SMD units) is beyond hope given the large amount of uncertainty we face even (or particularly) in modern science.
Hence, let’s assume that \(\mu=0.5\) in the following. For the sake of simplicity, I will assume that the parameter under investigation is normally distributed. However, more ink could (and should) be spilled on this question.
mu <- 0.5
As I think the uncertainty is large, we must allow for a relatively large standard deviation of the distribution of effects. Some reasons why I think the uncertainty in our population parameter value is lage include: publication bias, researcher degrees of freedom, variety in protocols and operationalization, plain errors in the course of a study, trickiness of nature, and more.
Hence, let’s take \(\sigma=.5\).
s <- 0.5
In sum:
\[\mu \sim \mathfreac{N}(0.5, 0.5)\]
What is the probability to observere a sample value larger less than zero?
p0 <- pnorm(q = 0, mean = 0.5, sd = .5) %>% round(2)
p0
#> [1] 0.16
In other words, we think that the probability that \(\mu \le 0\) equals to 0.16; let’s call it \(p_0\).
Given this model, we assume that the probability that the treatment is effective equals to \(p_1 = 1-p_0\), that is
p1 <- 1 - p0
p1
#> [1] 0.84
And so forth.
4 Drawing samples
Let’s draw multiple sample for different samples sizes and see how precisely we will measure the (true) population value. Than we can plot the precision of the population value estimation as a function of the sample size. In other words, we conduct some kind of power analysis.
5 Define some constants
Let’s define some auxiliary constants.
We’ll draw \(k\) sample of a given size:
k <- 100
Let’s check sample sizes according to the log 2 sequence:
x <- 1:15
n <- 2^x
n
#> [1] 2 4 8 16 32 64 128<PHONE_NUMBER> 2048 4096
#> [13] 8192 16384 32768
6 Simulating samples
6.1 SummayFunction to compute sample statistics
comp_sample_stats <- function(sample_size,
mu,
sigma) {
# draws sample and computes summary stats
sample_temp <- rnorm(n = sample_size,
mean = mu,
sd = sigma)
sample_mean <- mean(sample_temp)
sample_sd <- sd(sample_temp)
sample_se <- sample_sd / sqrt(n)
sample_ci_u <- sample_mean + 2 * sample_se
sample_ci_l <- sample_mean - 2 * sample_se
mu_in_ci <- (mu > sample_ci_l) & (mu < sample_ci_u)
zero_in_ci <- (sample_ci_l < 0) & (sample_ci_u > 0)
sample_stats <-
tibble(
avg = sample_mean,
stddev = sample_sd,
se = sample_se,
ci_u = sample_ci_u,
ci_l = sample_ci_l,
mu_in_ci = mu_in_ci,
zero_in_ci = zero_in_ci
)
return(sample_stats)
}
6.2 Run the function multiple (\(k\)) times
# sample_size <- 30 # delete me later!
comp_sample_stats_many_samples <-
function(sample_size,
mu,
sigma,
k # number of repetitions
) {
# draws sample and computes summary stats
# for k multiples samples
# of a fixed sample size
many_samples_results <-
1:k %>%
map_dfr( ~ comp_sample_stats(sample_size = sample_size,
mu = mu,
sigma = s),
.id = "id") %>%
mutate(n = sample_size,
id = as.numeric(id))
return(many_samples_results)
}
6.3 Run the summary function \(k\) times for all sample sizes
simulated_samples <-
n %>%
map_dfr( ~ comp_sample_stats_many_samples(
sample_size = .x,
mu = mu,
sigma = s,
k = k)) %>%
mutate(ci_width = ci_u - ci_l)
7 Plot the results
Remeber that all results presented here hinge of the assumption stated above. In particular, we have simulated \(k = 100\) samples.
7.1 Estimated population mean
p1 <- simulated_samples %>%
ggplot() +
aes(x = n, y = avg) +
geom_jitter(alpha = .03)
p1
As can be seen, all sample sizes greater than small do precisely show the true parameter (\(mu=0.5\)).
Let’s zoom in.
p1 +
xlim(0, 1024)
And even closer:
p1 +
xlim(0, 256)
Larger sample sizes yield stable estimates, as seen above. But even the difference between \(n=128\) and \(n=128\) (\(2^7, 2^8\)) appears negligible, from a practical point of view, given the large uncertainties associated with research study results in practice. Let’s remember that we should try to be more precise as it is possible (don’t estimate the age of the earth in seconds, rather in millions of years).
It appears that a sample size of 128 or even 64 is sufficiently precise to estimate the population effect size.
7.2 Width of the CI
p2 <- simulated_samples %>%
ggplot() +
aes(x = factor(n), y = ci_width) +
geom_boxplot(aes(group = n))
p2
Again, zoom in:
p3 <- simulated_samples %>%
filter(n <= 1024) %>%
ggplot() +
aes(x = factor(n), y = ci_width) +
geom_boxplot(aes(group = n))
p3
We can see that the width of the CI remains constant after an initial stabilizing phase. So, at say, \(n=32\) we already have stable width estimates.
8 Summarise the results
8.1 Compute summaries per sample size
simulated_samples_summarized <- simulated_samples %>%
group_by(n) %>%
summarise(across(
.cols = everything(),
.fn = list(avg = mean, sd = sd),
.names = "{.col}_{.fn}"))
glimpse(simulated_samples_summarized)
#> Rows: 15
#> Columns: 19
#> $ n <dbl> 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8…
#> $ id_avg <dbl> 50.5, 50.5, 50.5, 50.5, 50.5, 50.5, 50.5, 50.5, 50.5, 5…
#> $ id_sd <dbl> 28.8757, 28.8757, 28.8757, 28.8757, 28.8757, 28.8757, 2…
#> $ avg_avg <dbl> 0.4641198, 0.4601394, 0.5191425, 0.4979736, 0.5113036, …
#> $ avg_sd <dbl> 0.403764406, 0.271859795, 0.182014436, 0.115415684, 0.0…
#> $ stddev_avg <dbl> 0.3901300, 0.4498725, 0.4770262, 0.4808355, 0.4969101, …
#> $ stddev_sd <dbl> 0.291619823, 0.170001687, 0.126538119, 0.086169598, 0.0…
#> $ se_avg <dbl> 0.06244360, 0.07200590, 0.07635208, 0.07696179, 0.07953…
#> $ se_sd <dbl> 0.1091820, 0.1011893, 0.1020481, 0.0999563, 0.1023639, …
#> $ ci_u_avg <dbl> 0.5890070, 0.6041512, 0.6718467, 0.6518971, 0.6703729, …
#> $ ci_u_sd <dbl> 0.4627397, 0.3363836, 0.2745602, 0.2309151, 0.2234326, …
#> $ ci_l_avg <dbl> 0.3392326, 0.3161276, 0.3664384, 0.3440500, 0.3522342, …
#> $ ci_l_sd <dbl> 0.4552902, 0.3414320, 0.2723706, 0.2307593, 0.2240294, …
#> $ mu_in_ci_avg <dbl> 0.2066667, 0.3120000, 0.3833333, 0.4840000, 0.5346667, …
#> $ mu_in_ci_sd <dbl> 0.40504930, 0.46346435, 0.48636055, 0.49991060, 0.49896…
#> $ zero_in_ci_avg <dbl> 0.12000000, 0.13533333, 0.09466667, 0.09466667, 0.09466…
#> $ zero_in_ci_sd <dbl> 0.3250699, 0.3421933, 0.2928516, 0.2928516, 0.2928516, …
#> $ ci_width_avg <dbl> 0.2497744, 0.2880236, 0.3054083, 0.3078472, 0.3181386, …
#> $ ci_width_sd <dbl> 0.4367281, 0.4047573, 0.4081926, 0.3998252, 0.4094558, …
8.2 Plot the (summarized) results
simulated_samples_summarized %>%
ggplot() +
aes(x = n, y = avg_avg,
ymin = avg_avg - avg_sd,
ymax = avg_avg + avg_sd
) +
geom_ribbon(alpha = .5) +
geom_point() +
xlim(0, 128) +
labs(x = "Sample size",
y = "Average across 100 samples",
caption = "The ribbon shows the interval [mean ± se]")
9 Conclusions
9.1 Small sample may suffice
Under well-defined situations such as the one presented here, small samples are sufficient.
However, it must be stressed that this comfortable conclusions hinges on the assumptions stated above.
9.2 Situations in which small samples will not suffice
The standard errors (for the mean value) increases as a function of variability (standard deviation, ie., sigma) in the population. The well-known formula for SE is valid only in the normal distribution scenario. If we assumed different distributions for the population parameter \(\mu\), we would arrive, in most situation, at much larger samples sizes.


Module io
This module provides functions for reading and writing streams of raw bytes.
It implements the Stream
and TextStream
classes as per
the CommonJS IO/A proposal.
Streams are closely related with two other modules. Low-level byte manipulation is provided
by the binary
module
and uses the ByteArray
or ByteString
class. The
fs
module returns io
streams for reading and
writing files.
Class MemoryStream
Instance Methods
- close()
- closed()
- flush()
- read(maxBytes)
- readInto(buffer, begin, end)
- readable()
- seekable()
- writable()
- write(source, begin, end)
Instance Properties
Class Stream
Instance Methods
- close()
- closed()
- copy(output)
- flush()
- forEach(fn, [thisObj])
- read(maxBytes)
- readInto(buffer, begin, end)
- readable()
- seekable()
- skip(num)
- unwrap()
- writable()
- write(source, begin, end)
Instance Properties
Class TextStream
Instance Methods
- close()
- copy(output)
- flush()
- forEach(callback, [thisObj])
- iterator()
- next()
- print()
- read()
- readInto()
- readLine()
- readLines()
- readable()
- seekable()
- writable()
- write()
- writeLine(line)
- writeLines(lines)
Instance Properties
MemoryStream (binaryOrNumber)
A binary stream that reads from and/or writes to an in-memory byte array.
If the constructor is called with a Number argument, a ByteArray with the given length is allocated and the length of the stream is set to zero.
If the argument is a binary object it will be used as underlying buffer and the stream length set to the length of the binary object. If argument is a ByteArray, the resulting stream is both readable, writable, and seekable. If it is a ByteString, the resulting stream is readable and seekable but not writable.
If called without argument, a ByteArray of length 1024 is allocated as buffer.
Parameters
| Binary|Number | binaryOrNumber | the buffer to use, or the initial capacity of the buffer to allocate. |
MemoryStream.prototype.close ()
Closes the stream, freeing the resources it is holding.
MemoryStream.prototype.closed ()
Returns true if the stream is closed, false otherwise.
Returns
| Boolean | true if the stream has been closed |
MemoryStream.prototype.content
The wrapped buffer.
MemoryStream.prototype.flush ()
Flushes the bytes written to the stream to the underlying medium.
MemoryStream.prototype.length
The number of bytes in the stream's underlying buffer.
MemoryStream.prototype.position
The current position of this stream in the wrapped buffer.
MemoryStream.prototype.read (maxBytes)
Read up to maxBytes
bytes from the stream, or until the end of the stream
has been reached. If maxBytes
is not specified, the full stream is read
until its end is reached. Reading from a stream where the end has already been
reached returns an empty ByteString.
Parameters
| Number | maxBytes | the maximum number of bytes to read |
Returns
| ByteString |
MemoryStream.prototype.readInto (buffer, begin, end)
Read bytes from this stream into the given buffer. This method does not increase the length of the buffer.
Parameters
| ByteArray | buffer | the buffer |
| Number | begin | optional begin index, defaults to 0. |
| Number | end | optional end index, defaults to buffer.length - 1. |
Returns
| Number | The number of bytes read or -1 if the end of the stream has been reached |
MemoryStream.prototype.readable ()
Returns true if the stream supports reading, false otherwise. Always returns true for MemoryStreams.
Returns
| Boolean | true if stream is readable |
MemoryStream.prototype.seekable ()
Returns true if the stream is randomly accessible and supports the length and position properties, false otherwise. Always returns true for MemoryStreams.
Returns
| Boolean | true if stream is seekable |
MemoryStream.prototype.writable ()
Returns true if the stream supports writing, false otherwise. For MemoryStreams this returns true if the wrapped binary is an instance of ByteArray.
Returns
| Boolean | true if stream is writable |
MemoryStream.prototype.write (source, begin, end)
Write bytes from b to this stream. If begin and end are specified, only the range starting at begin and ending before end is written.
Parameters
| Binary | source | The source to be written from |
| Number | begin | optional |
| Number | end | optional |
Stream ()
This class implements an I/O stream used to read and write raw bytes.
Stream.prototype.close ()
Closes the stream, freeing the resources it is holding.
Stream.prototype.closed ()
Returns true if the stream has been closed, false otherwise.
Returns
| Boolean | true if the stream has been closed |
Stream.prototype.copy (output)
Reads all data available from this stream and writes the result to the given output stream, flushing afterwards. Note that this function does not close this stream or the output stream after copying.
Parameters
| Stream | output | The target Stream to be written to. |
Stream.prototype.flush ()
Flushes the bytes written to the stream to the underlying medium.
Stream.prototype.forEach (fn, [thisObj])
Read all data from this stream and invoke function fn
for each chunk of data read.
The callback function is called with a ByteArray as single argument. Note that
the stream is not closed after reading.
Parameters
| Function | fn | the callback function |
| Object | [thisObj] | optional this-object to use for callback |
Stream.prototype.inputStream
The wrapped java.io.InputStream
.
Stream.prototype.outputStream
The wrapped java.io.OutputStream
.
Stream.prototype.read (maxBytes)
Read up to maxBytes
bytes from the stream, or until the end of the stream
has been reached. If maxBytes
is not specified, the full stream is read
until its end is reached. Reading from a stream where the end has already been
reached returns an empty ByteString.
Parameters
| Number | maxBytes | the maximum number of bytes to read |
Returns
| ByteString |
Stream.prototype.readInto (buffer, begin, end)
Read bytes from this stream into the given buffer. This method does not increase the length of the buffer.
Parameters
| ByteArray | buffer | the buffer |
| Number | begin | optional begin index, defaults to 0. |
| Number | end | optional end index, defaults to buffer.length - 1. |
Returns
| Number | The number of bytes read or -1 if the end of the stream has been reached |
Stream.prototype.readable ()
Returns true if the stream supports reading, false otherwise.
Returns
| Boolean | true if stream is readable |
Stream.prototype.seekable ()
Returns true if the stream is randomly accessible and supports the length and position properties, false otherwise.
Returns
| Boolean | true if stream is seekable |
Stream.prototype.skip (num)
Try to skip over num bytes in the stream. Returns the number of acutal bytes skipped or throws an error if the operation could not be completed.
Parameters
| Number | num | bytes to skip |
Returns
| Number | actual bytes skipped |
Stream.prototype.unwrap ()
Get the Java input or output stream instance wrapped by this Stream.
Stream.prototype.writable ()
Returns true if the stream supports writing, false otherwise.
Returns
| Boolean | true if stream is writable |
Stream.prototype.write (source, begin, end)
Write bytes from b to this stream. If begin and end are specified, only the range starting at begin and ending before end is written.
Parameters
| Binary | source | The source to be written from |
| Number | begin | optional |
| Number | end | optional |
TextStream (io, options, buflen)
A TextStream implements an I/O stream used to read and write strings. It wraps a raw Stream and exposes a similar interface.
Parameters
| Stream | io | The raw Stream to be wrapped. |
| Object | options | the options object. Supports the following properties:
|
| number | buflen | optional buffer size. Defaults to 8192. |
TextStream.prototype.content
If the wrapped stream is a MemoryStream this contains its content decoded to a String with this streams encoding. Otherwise contains an empty String.
TextStream.prototype.copy (output)
Reads from this stream with readLine, writing the results to the target stream and flushing, until the end of this stream is reached.
Parameters
| output |
Returns
| TextStream | this stream |
TextStream.prototype.forEach (callback, [thisObj])
Calls callback
with each line in the input stream.
Example
var txtStream = fs.open('./browserStats.csv', 'r'); txtStream.forEach(function(line) { console.log(line); // Print one single line });
Parameters
| Function | callback | the callback function |
| Object | [thisObj] | optional this-object to use for callback |
TextStream.prototype.next ()
Returns the next line of input without the newline. Throws
StopIteration
if the end of the stream is reached.
Example
var fs = require('fs'); var txtStream = fs.open('./browserStats.csv', 'r'); try { while (true) { console.log(txtStream.next()); } } catch (e) { console.log("EOF"); }
Returns
| String | the next line |
TextStream.prototype.print ()
Writes all argument values as a single line, delimiting the values using a single blank.
Example
>> var fs = require('fs'); >> var txtOutStream = fs.open('./demo.txt', 'w'); >> txtOutStream.print('foo', 'bar', 'baz'); // demo.txt content: foo bar baz
Returns
| TextStream | this stream |
TextStream.prototype.raw
The wrapped binary stream.
TextStream.prototype.read ()
Read the full stream until the end is reached and return the data read as string.
Returns
| String |
TextStream.prototype.readInto ()
Not implemented for TextStream
. Calling this method will raise an error.
TextStream.prototype.readLine ()
Reads a line from this stream. If the end of the stream is reached before any data is gathered, returns an empty string. Otherwise, returns the line including only the newline character. Carriage return will be dropped.
Returns
| String | the next line |
TextStream.prototype.readLines ()
Returns an Array of Strings, accumulated by calling readLine
until it
returns an empty string. The returned array does not include the final
empty string, but it does include a trailing newline at the end of every
line.
Example
>> var fs = require('fs'); >> var txtStream = fs.open('./sampleData.csv', 'r'); >> var lines = txtStream.readLines(); >> console.log(lines.length + ' lines'); 6628 lines
Returns
| Array | an array of lines |
TextStream.prototype.seekable ()
Always returns false, as a TextStream is not randomly accessible.
TextStream.prototype.write ()
Writes all arguments to the stream.
Example
>> var fs = require('fs'); >> var txtOutStream = fs.open('./demo.txt', 'w'); >> txtOutStream.write('foo', 'bar', 'baz'); // demo.txt content: foobarbaz
Returns
| TextStream | this stream |
TextStream.prototype.writeLine (line)
Writes the given line to the stream, followed by a newline.
Parameters
| line |
Returns
| TextStream | this stream |
TextStream.prototype.writeLines (lines)
Writes the given lines to the stream, terminating each line with a newline.
This is a non-standard extension, not part of CommonJS IO/A.
Parameters
| lines |
Returns
| TextStream | this stream |


--- layout: post title: "Some thoughts on naming tests" description: "What is the purpose of a test name?" date: 2022-06-13 7:51 UTC tags: [Unit Testing, Code] --- {% include JB/setup %}
{{ page.description }}
Years ago I was participating in a coding event where we did katas. My pairing partner and I was doing silent ping pong. Ping-pong style pair programming is when one programmer writes a test and passes the keyboard to the partner, who writes enough code to pass the test. He or she then writes a new test and passes control back to the first person. In the silent variety, you're not allowed to talk. This is an exercise in communicating via code.
My partner wrote a test and I made it pass. After the exercise was over, we were allowed to talk to evaluate how it went, and my partner remarked that he'd been surprised that I'd implemented the opposite behaviour of what he'd intended. (It was something where there was a fork in the logic depending on a number being less than or greater to zero; I don't recall the exact details.)
We looked at the test that he had written, and sure enough: He'd named the test by clearly indicating one behaviour, but then he'd written an assertion that looked for the opposite behaviour.
I hadn't even noticed.
I didn't read the test name. I only considered the test body, because that's the executable specification.
I've been thinking about test names ever since. What is the role of a test name?
In some languages, you write unit tests as methods or functions. That's how you do it in C#, Java, and many other languages:
[Theory] [InlineData("Home")] [InlineData("Calendar")] [InlineData("Reservations")] public void WithControllerHandlesSuffix(string name) { var sut = new UrlBuilder(); var actual = sut.WithController(name + "Controller"); var expected = sut.WithController(name); Assert.Equal(expected, actual); }
Usually, when we define new class methods, we've learned that naming is important. Truly, this applies to test methods, too?
Yet, other languages don't use class methods to define tests. The most common JavaScript frameworks don't, and neither does Haskell HUnit. Instead, tests are simply values with labels.
This hints at something that may be important.
If tests aren't necessarily class methods, then what role do names play?
Usually, when considering method names, it's important to provide a descriptive name in order to help client developers. A client developer writing calling code must figure out which methods to call on an object. Good names help with that.
Automated tests, on the other hand, have no explicit callers. There's no client developer to communicate with. Instead, a test framework such as xUnit.net scans the public API of a test suite and automatically finds the test methods to execute.
The most prominent motivation for writing good method names doesn't apply here. We must reevaluate the role of test names, also keeping in mind that with some frameworks, in some languages, tests aren't even methods.
The story that introduces this article has a point. When considering a test, I tend to go straight to the test body. I only read the test name if I find the test body unclear.
Does this mean that the test name is irrelevant? Should we simply number the tests: Test1
, Test212
, and so on?
That hardly seems like a good idea - not even to a person like me who considers the test name secondary to the test definition.
This begs the question, though: If Test42
isn't a good name, then what does a good test name look like?
Various people suggest naming schemes. In the .NET world many people like Roy Osherove's naming standard for unit tests: [UnitOfWork_StateUnderTest_ExpectedBehavior]
. I find it too verbose to my tastes, but my point isn't to attack this particular naming scheme. In my Types + Properties = Software article series, I experimented with using a poor man's version of Given When Then:
[<Property>] let ``Given deuce when player wins then score is correct`` (winner : Player) = let actual : Score = scoreWhenDeuce winner let expected = Advantage winner expected =! actual
It was a worthwhile experiment, but I don't think I ever used that style again. After all, Given When Then is just another way of saying Arrange Act Assert, and I already organise my test code according to the AAA pattern.
These days, I don't follow any particular naming scheme, but I do keep a guiding principle in mind.
A test name, whether it's a method name or a label, is an opportunity to communicate with the reader of the code. You can communicate via code, via names, via comments, and so on. A test name is more like a mandatory comment than a normal method name.
Books like Clean Code make a compelling case that comments should be secondary to good names. The point isn't that all comments are bad, but that some are:
var z = x + y; // Add x and y
It's rarely a good idea to add a comment that describes what the code does. This should already be clear from the code itself.
A comment can still provide important information that code can't easily do. It may explain the purpose of the code. I try to take this into account when naming tests: Not repeat what the code does, but suggest a hint about its raison d'être.
I try to strike a balance between Test2112
and Given deuce when player wins then score is correct
. I view the task of naming tests as equivalent to producing section headings in an article like this one. They offer a hint at the kind of information that might be available in the section (The role of test names, How tests are named, or Information channel), but sometimes they're more tongue-in-cheek than helpful (Mere anarchy is loosed upon the world). I tend to name tests with a similar degree of precision (or lack thereof): HomeReturnsJson
, NoHackingOfUrlsAllowed
, GetPreviousYear
, etcetera.
These names, in isolation, hardly tell you what the tests are about. I'm okay with that, because I don't think that they have to.
I occasionally discuss this question with other people. It seems to me that it's one of the topics where Socratic questioning breaks down:
Them: How do you name tests?
Me: I try to strike a balance between information and not repeating myself.
Them: How do you like this particular naming scheme?
Me: It looks verbose to me. It seems to be repeating what's already in the test code.
Them: I like to read the test name to see what the test does.
Me: If the name and test code disagree, which one is right?
Them: The test name should follow the naming scheme.
Me: Why do you find that important?
Them: It's got... electrolytes.
Okay, I admit that I'm a being uncharitable, but the point that I'm after is that test names are different, yet most people seem to reflect little on this.
When do you read test names?
Personally, I rarely read or otherwise use test names. When I'm writing a test, I also write the name, but at that point I don't really need the name. Sometimes I start with a placeholder name (Foo
), write the test, and change the name once I understand what the test does.
Once a test is written, ideally it should just be sitting there as a regression test. The less you touch it, the better you can trust it.
You may have hundreds or thousands of tests. When you run your test suite, you care about the outcome. Did it pass or fail? The outcome is the result of a Boolean and operation. The test suite only passes when all tests pass, but you don't have to look at each test result. The aggregate result is enough as long as the test suite passes.
You only need to look at a test when it fails. When this happens, most tools enable you to go straight to the failing test by clicking on it. (And if this isn't possible, I usually find it easier to navigate to the failing test either by line number or by copying the test name and navigating to it by pasting the name into my editor's navigation UI.) You don't really need the name to find a failing test. If the test was named Test1337
it would be as easy to find as if it was named Given deuce when player wins then score is correct
.
Once I look at a failing test, I start by looking at the test code and comparing that to the assertion message.
Usually, when a test fails, it breaks for a reason. A code change caused the test to fail. Often, the offending change was one you did ten seconds earlier. Armed with an assertion message and the test code, I usually understand the problem right away.
In rare cases the test is one that I've never seen before, and I'm confused about its purpose. This is when I read the test name. At that point, I appreciate if the name is helpful.
I'm puzzled that people are so passionate about test names. I consider them the least important part of a test. A name isn't irrelevant, but I find the test code more important. The code is an executable specification. It expresses the desired truth about a system.
Test code is code that has the same lifetime as the production code. It pays to structure it as well as the production code. If a test is well-written, you should be able to understand it without reading its name.
That's an ideal, and in reality we are fallible. Thus, providing a helpful name gives the reader a second chance to understand a test. The name shouldn't, however, be your first priority.
Comments
I often want run selected tests from the command line and thus use the test runner's abilty to filter all available tests. Where the set of tests I want to run is all the tests below some point in the heirarchy of tests I can filter by the common prefix, or the test class name.
But I also often find myself wanting to run a set of tests that meet some functional criteria, e.g Validation approval tests, or All the tests for a particular feature across all the levels of the code base. In this case if the tests follow a naming convention where such test attributes are included in the test name, either via the method or class name, then such test filtering is possible.
Mark, are you a Classicist or a Mockist? I'm going to go out on a limb here and say you're probably a classicist. Test code written in a classicist style probably conveys the intent well already. I think code written in a Mockist style may not convey the intent as well, hence the test name (or a comment) becomes more useful to convey that information.
There are (at least) two ways of using test names (as well as test module names, as suggested by Struan Judd) that we make extensive use of in the LinkedIn code base and which I have used in every code base I have ever written tests for:
To indicate the intent of the test. It is well and good to say that the assertions should convey the conditions, but often it is not clear why a condition is intended to hold. Test names (and descriptive strings on the assertions) can go a very long way, especially when working in a large and/or unfamiliar code base, to understand whether the assertion remains relevant, or how it is relevant.
Now, granted: it is quite possible for those to get out of date, much as comments do. However, just as good comments remain valuable even though there is a risk of stale comments, good test names can be valuable even though they can also become stale.
The key, for me, is exactly the same as good comments—and you could argue that comments therefore obviate the need for test names. If we only cared about tests from the POV of reading the code, I would actually agree! However, because we often read the tests as a suite of assertions presented in some other UI (a terminal, a web view, etc.), the names and assertion descriptions themselves serve as the explanation when reading.
To provide structure and organization to the test suite. This is the same point Struan Judd was getting at: having useful test names lets you filter down to relevant chunks of the suite easily. This is valuable even on a small code base (like the
Maybe
andResult
library in TypeScript a friend and I maintain), but it becomes invaluable when you have tens of thousands of tests to filter or search through, as in the main LinkedIn app!For that reason, we (and the Ember.js community more broadly) make extensive use of QUnit's
module()
hook to name the set of modules under test (module('Rendering | SomeComponent', function () { ... }
ormodule('Unit | some-utility', function () { ... }
) as well as namingtest()
(test('returns `null` if condition X does not hold', function (assert) { ... }
) and indeed providing descriptive strings forassert()
calls. We might even nestmodule()
calls to make it easy to see and filter from how our test UI presents things: Rendering | SomeComponent > someMethod > a test description.Now, how that plays out varies library to library. The aforementioned TS library just names the test with a decent description of what is under test (here, for example) as well as grouping them sensibly with overarching descriptions, and never uses assertion descriptions because they wouldn’t add anything. A couple of the libraries I wrote internally at LinkedIn, by contrast, make extensive use of both. It is, as usual, a tool to be employed as, and only as, it is useful. But it is indeed quite useful sometimes!
Struan, thank you for writing. I can't say that I've given much thought to the need to run subsets of a test suite. You have a point, though, that if that's a requirement, you need something on which to filter.
Is the name the appropriate criterion for that, though? It sounds brittle to me, but I grant that it depends on which alternatives are available. In xUnit.net, for example, you can use the
[Trait]
attribute to annotate tests with arbitrary metadata. I think that NUnit has a similar feature, but there's no guarantee that every unit testing framework on any platform or language supports such a feature.Whenever a framework supports such metadata-based filtering, I'd favour relying on that instead of naming conventions. Naming conventions are vulnerable to misspellings and other programmer errors. That may also be true of metadata-based categorisation, but hopefully to a lesser degree, as these might enable you to use ordinary language features to keep the categories DRY.
Using names also sounds restrictive to me. Doesn't this mean that you have to be able to predict your filtering requirements when you decide on a naming scheme?
What if, later, you find that you need to filter on a different dimension? With metadata annotations, you should be able to add a new category to the affected tests, but how will you do that with an established naming scheme?
Overall, though, the reason that I haven't given this much thought is that I've never had the need to filter tests in arbitrary ways. You must be doing something different from how I work with tests. Why do you need to filter tests?
Eddie, thank you for writing. I don't find the linked article illuminating if one hasn't already heard about the terms mockist and classicist. I rather prefer the terms interaction-based and state-based testing. In any case, I started out doing interaction-based testing, but have since moved away from that. Even when I mainly wrote interaction-based tests, though, I didn't like rigid naming schemes. I don't see how that makes much of a difference.
I agree that a test name is a fine opportunity to convey intent. Did that not come across in the article?
Chris, thank you for writing. As I also responded to Eddie Stanley, I agree that a test name is a fine opportunity to convey intent. Did that not come across in the article?
To your second point, I'll refer you to my answer to Struan Judd. I'm still curious to learn why you find it necessary to categorise and filter tests.


Fetch data using REST-service, expand rows and display a custom component, use custom functions for rendering, sorting and exporting. Apply predefined filter and simple function for adding new random data to table. To control columns we use the ColumnSettingsComponent
. This example also utilizes column stacking on tablets and mobile devices so resize the browser and see what happens with the layout on smaller screens.
[gtOptions]="{{ '{' }}numberOfRows:0{{ '}' }}"
or by passing 'all'
to the changeRowLength
method like in the example below, generic table still needs to render a lot of rows which currently makes it a bit unresponsive. Hopefully this will be improved in future releases but in the meantime it's recommended to limit the number of rendered rows and use pagination as it allows you to "display" hundreds of thousands rows.


THE BIRDCAGE A film review by Ben Hoffman Copyright 1996 Ben Hoffman
It was way back in 1978 that La Cage Aux Folles, the hilarious French film about homosexuals, the transvestite nightclub, the owner, his partner (in more ways than one), first arrived here. It was an instant critical and box office success. That could only mean one thing: a sequel. Three years later that arrived but the truism about sequels held and so that was an instant flop. Since everyone thinks "I can do anything better than you," another sequel arrived 3 years later and it was an abomination. That brings us to today's version, "The birdcage ." directed by Mike Nichols and oooh!. Vive la difference..
Nichols' version brings the story not merely up to date but demonstrates the difference between the "family values." rightwing politicians are pushing and what the value of a family really is. And Nichols' direction plus Elaine May's script are right on target.
About the cast: Everyone is exactly right; the casting is perfect. So much has been said and written about Robin Williams (who here plays the father of a "straight" son) it is almost superfluous to say more. But in a couple of seconds he can take you from laughter to tears and back. Would that there were more fathers like Armand Goldman, the gay father.
In the most wonderful performance of a very successful career in cinema, the one who got to me as the most brilliant was Dianne Weist as Louise Keeley, the wife of the conservative Senator (Gene Hackman) who are the parents of the lovely Barbara (Calista Flockhart). Special mention should be made, too, of Dan Futterman. who plays Armand's loving, devoted son to his father and father's partner, Albert (Nathan Lane.) Lane, who is mostly known for his work on the Broadway stage, is terrific. The whole movie is terrific. Did I like it? No, I loved it..
4 BYTES
4 Bytes = Superb 3 Bytes = Too good to miss 2 Bytes = Average 1 Byte = Save your money
Copyright 1996 Ben Hoffman
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Hello, my name is Gerardo and I write from Italy, I would like to make a monitoring DC. I have a switching power supply DC 10A max. I would like to calculate the current DC. I thought this sensor:
http://www.yhdc.com/en/product/366/
model HA2009-20A / 50mA
Kindly anyone can help me to reliazzare scketc?
Re: DC Monitoring with Hall effect sensor
That sensor will probably work. It will need a power supply that is separate from your emonTx (or Arduino), that will give ± 12V - ±18V, and the 0 V from that power supply will connect to the emonTx GND. The output is a current of 50 mA (for 20 A primary current), therefore you calculate the value of RM to give 3.3 V (5 V for Arduino) or a little less at 25 mA.
Re: DC Monitoring with Hall effect sensor
Hello Robert
I want to use Arduino to 5 v, for interfacing the sensor with arduino I have to use some circuit?
or I can use this:
http://openenergymonitor.org/emon/buildingblocks/ct-sensors-interface
calculating the different resistances
Re: DC Monitoring with Hall effect sensor
No, you cannot use the circuit for a CT. It is for a CT only. Use the standard Arduino circuit for measuring d.c.
You connect the GND of your Arduino to 0 V of your dual power supply, and you connect pin 3 of the sensor to the Analogue input of your Arduino. Do not forget the resistor RM.
Then in the sketch, you use analogRead(x) to get the current. ('x' is your input pin). The number you get should go from 0 to 1023 for 0 to 10 A, but of course it will not, exactly.
There might be an offset, meaning you read a non-zero number with no current. To correct that you add a constant value.
There might be a scale error, meaning that you need to multiply the number you read by a correction factor so that when you have 10 A, you read 10 A.
Your code within setup( ) might look like this:
double m = 1.0 // change this to adjust the scale calibration
double c = 0.0 // change this to remove any offset
Your code within loop( ) might look like this:
double dcAmps = analogRead(x) * 10.00/1024 * m - c;
Serial.println(dcAmps);
Re: DC Monitoring with Hall effect sensor
Hello Robert,
what is the resistor RM??
thank you


For your safety, remain seated, keeping your hands, arms, feet, and legs inside the boat. And no
flash pictures, please!
It's A Tiled World After All
Hi!
GIS & Cartography
OSM US Board Member
Vector Tiles: your data, compact, and tiled for SUPER fast rendering
Style: how your data gets rendered (think css)
Client: code library that reads your vector tiles from a style
global properties
functions
style layout
no gui
shaders are hard
Comparable vs Mapbox Studio
Full JSON & GUI
Open Development
Behind on Style Spec
check out
Show & Tell for examples of Maputnik in action
Projections!
Desktop Publishing
Not WYSIWYG
Unsupported Spec Items
Lots of legwork to customize
Experiment Time!
1. focal statistics
2. hillshade
3. reclassify
4. raster 2 poly


Every minute you spend looking for the right tools to accomplish what you need is a minute more you'll be working on your project. Let's make it as easy as possible to find the tools you need.
js-tools is very much a work in progress, and it needs your help to improve and expand. If you have time, please and contribute something.


{{ date | date:'longDate'}}
activityRunsheet_Packways_{{activityRunsheet.ref}}
{{activityRunsheet.status}} - Driver: {{(!!activityRunsheet.driver) ? activityRunsheet.driver.nameDriver + " " + activityRunsheet.driver.surnameDriver : "n'est pas assigné"}}
{{ activityRunsheet.createdDate | date:'dd/MM/yyyy'}}
2}" class="mt-2"> {{ calculateDiff(activityRunsheet.createdDate)}} Jours


Folders
<parent>
file-utilities
is-valid-file-name
recursive...folder
file-name...m-path
guessing-game
Folders: 6


We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.


Hamburger Menu Options
It looks like three hotdogs, doesn't it?
or
Or a patty with two buns, whatever.
Custom Overrides
Host
CSS Selector
Actions


API Endpoint
Headers to be passed [Provide as key-value pair(JSON format)]
Sample Input to be passed by the user [Provide as key-value pair(JSON format)]
Sample Input to be passed by the user [Provide as key-value pair(JSON format)]
Output parameter to index from model output[give comma separated list]


Addidas running
Price : CAD 99
Addidas Light Air
Price : CAD 100
air-max running
Price : CAD 129
Addidas basketball
Price : CAD 164
Air-max power running
Price : CAD 110
Nike men ruff
Price : CAD 111
Nike power running
Price : CAD 89
nike light
Price : CAD 120
Nike color
Price : CAD 45
nike Ruff and tuff
Price : CAD 199
Addidas Light weight
Price : CAD 136
NK shoes is started on september ,8, 2001 is engaged with design,development,marketing and selling of sport shoes.
NK shoes sells its product to retail customer and its have many retail stores all over
the world and website to selling worldwide.


static
variables whose names are either too short, too long,
or do not follow
the specified regular expression pattern.
Constants, i.e. variables of immutable type declared
static final
, are not checked by this inspection
Use the fields provided below to specify minimum length, maximum length and regular expression expected for static variable names
(Regular expressions are in standard java.util.regex.Pattern
format).


Utopia::HTTP
HTTP protocol implementation.
Nested
Definitions
Accept = ::HTTP::Accept
Pull in ::HTTP::Accept
for parsing.
STATUS_CODES = {...}
A list of commonly used HTTP status codes. For help choosing the right status code, see http://racksburg.com/choosing-an-http-status-code/
Implementation
STATUS_CODES = {
:success => 200,
:created => 201,
:accepted => 202,
:moved => 301,
:found => 302,
:see_other => 303,
:not_modified => 304,
:redirect => 307,
:bad_request => 400,
:unauthorized => 401,
:forbidden => 403,
:not_found => 404,
:not_allowed => 405,
:unsupported_method => 405,
:gone => 410,
:teapot => 418,
:unprocessible => 422, # The best status code for a client-side ArgumentError.
:error => 500,
:unimplemented => 501,
:unavailable => 503
}
STATUS_DESCRIPTIONS
A list of human readable descriptions for a given status code. For a more detailed description, see https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
Implementation
STATUS_DESCRIPTIONS = {
200 => 'OK'.freeze,
201 => 'Created'.freeze,
202 => 'Accepted'.freeze,
203 => 'Non-Authoritive Information'.freeze,
204 => 'No Content'.freeze,
205 => 'Reset Content'.freeze,
206 => 'Partial Content'.freeze,
300 => 'Multiple Choices'.freeze,
301 => 'Moved Permanently'.freeze,
302 => 'Found'.freeze,
303 => 'See Other'.freeze,
304 => 'Not Modified'.freeze,
305 => 'Use Proxy'.freeze,
307 => 'Temporary Redirect'.freeze,
308 => 'Permanent Redirect'.freeze,
400 => 'Bad Request'.freeze,
401 => 'Permission Denied'.freeze,
402 => 'Payment Required'.freeze,
403 => 'Access Forbidden'.freeze,
404 => 'Resource Not Found'.freeze,
405 => 'Unsupported Method'.freeze,
406 => 'Not Acceptable'.freeze,
408 => 'Request Timeout'.freeze,
409 => 'Request Conflict'.freeze,
410 => 'Resource Removed'.freeze,
416 => 'Byte range unsatisfiable'.freeze,
422 => 'Unprocessible Entity'.freeze,
500 => 'Internal Server Error'.freeze,
501 => 'Not Implemented'.freeze,
503 => 'Service Unavailable'.freeze
}.merge(Rack::Utils::HTTP_STATUS_CODES)


She seems to hide all looks that have ever fallen
into her, so that, like an audience,
she can look them over, menacing and sullen,
and curl to sleep with them.


Designed by developers for developers, the Nuxeo Platform is a highly customizable and extensible content management platform for building business applications.
Nuxeo Drive enables bidirectional synchronization of content between the local desktop and the Nuxeo content repository, on premise or in the Cloud.
The Nuxeo Mobile App for iOS provides a seamless experience on main features such as search, browsing and working on your favorite assets.
Integrate enterprise content and digital assets with related Salesforce objects.
Provides key digital asset management functionality directly within Adobe Creative Suite applications.
Integration to Google Drive, Dropbox, Box, OneDrive and Microsoft Office 365.
Integration with the Google Cloud Vision image detection service.
An Eclipse-based Integrated Development Environment.
Enables the bootstrapping of several Nuxeo elements like Operation, Service, Package,...
Functional and load web tester developed by Nuxeo.
available that offers an interactive way to discover the Nuxeo Platform API.


Stacks in python
Stacks are a type of data structure following the premise of first in, last out.
A common way to look at this is to look literally at a stack, for example a stack of books. The first put in will be the last one out as it is on the bottom.
Queues in python
Queues are another example of a type of data structure, this time following with FIFO (First In First Out) for data.
Similar to the stack data structure, queues follow a logical real world comparison. The first in a queue for example to see a film, will be the first into the film.
In the same way data that enters first, will leave the data structure first.


Your webserver is working successfully.
As you can see, scss is preprocess to css, and assets are served up.


WebConsole
Connect
Please connect with the Unreal instance running WebConsole
IP Address and port
The IP address and port the Unreal instance is running at
Password
The WebConsole password you specified in your project settings
Remember credentials
Get all logs on startup
Connect
Error!
The password you entered was incorrect!
Error!
There was an error connecting to your WebConsole. Is the IP correct?
Auto scroll
Clear Log
Made with
♥
for Unreal - created by
Johnny Verbeek
Check it out on
𝖀⁴ Marketplace


|
| OpenAFP.Types.Buffer | | Portability | non-portable (GHC-only) | | Stability | experimental | | Maintainer |<EMAIL_ADDRESS>|
|
|
|
|
|
| Description |
| This module handles sized binary buffers.
|
|
| Synopsis |
|
|
|
| Documentation |
|
| class (Show a, Typeable a) => Buf a where |
| The Buf class represents buffers, with the leading bytes
representing its length. | | | Methods | | | | Instances | |
|
|
| newtype Buffer0 |
| Buffer0, being a simple PStringLen, is of unlimited length. | | Constructors | | | Instances | |
|
|
| newtype Buffer1 |
| Buffer1 uses one byte as length, hence is at most 254 bytes long. | | Constructors | | | Instances | |
|
|
| newtype Buffer2 |
| Buffer2 uses two bytes; it can store up to 65535 bytes. | | Constructors | | | Instances | |
|
|
| Produced by Haddock version ADDOCK_VERSION |


@(positions: List[models.Position], players: List[models.Player],team: models.Team, user: models.User)
@main("Squad",user) {
is your current squad
| Jersey Number |
Player Name |
team id |
GK |
Def |
Mid |
Atck |
Health |
Injured |
Training |
Position |
Transfer |
@for(player <- players ){
@if(1 == 1){
| @player.jerseyNum |
@player.playerName |
@player.teamID |
@player.gkVal |
@player.defVal |
@player.midFVal |
@player.attVal |
@player.health |
@if(player.injury == true){
Yes
}else{
No
}
|
|
|
|
}
}
@helper.form(action = routes.PlayerCtrl.genStats) {
}
}


All 5 members of Team RAW revealed for Survivor Series 2019
by Abhilash MendheOn tonight's edition of Monday Night RAW, Charlotte Flair was revealed as the Red brand's team captain for the 15-woman Triple Threat Elimination Match at Survivor Series 2019. The other four members of Team RAW were also announced.
At Survivor Series 2019, all three WWE brands will collide in a series of Triple Threat matches. For years now, we have seen Monday Night RAW and Friday Night SmackDown face off in interbrand matches at Survivor Series. This time though, NXT will join in on the fun and try to reign supreme over the main roster brands.
One of the bouts at the event will be a 15-Woman Triple Threat Elimination Match, with five Superstars from each show representing their respective brand. Tonight on RAW, Charlotte Flair was announced as the captain for Monday Night RAW's female team.
Natalya, Sarah Logan, and WWE Women's Tag Team Champions The Kabuki Warriors (Asuka & Kairi Sane) will join Flair on the team. With Survivor Series almost on the horizon, we are bound to find out the five members of Team NXT on Wednesday's show.
We want to know what you think of the matches that you see on TV! Go to our WWE page here and rate and comment what you thought of them!


Datasets
Patient History
User Data Store
Available Datasets
Use Dataset
Age at Dx
Survival
Reset
View
Edit
Delete
Annotate and Save New Selection
Name
Tags
Save
Cancel


The application will return one opaqueResultData file for each request that was successfully processed. For example a web map service application would return an image file for each map request.


Nadal confirms London ATP Finals place
Madrid - World No 1 Rafael Nadal, recovering from injury, confirmed on Tuesday he will compete at the season-ending ATP Tour Finals in London from November 10-17.
"Yesterday I had an MRI in Majorca and despite a slight strain to the left abdominal muscle I will go to London," tweeted Nadal, forced out of last week's Paris Masters by the same injury.
"Thursday or Friday I will start hitting services. The idea is to play the ATP Finals. Thanks for your support."
Nadal took over as world No 1 this week from Novak Djokovic who went on to win the Paris Masters.
The eight top-ranked players in the world gather in London for the ATP Tour Finals where Nadal's world No 1 ranking will be under threat from Djokovic.
The Serb would be sure of reclaiming the year-end top ranking should he win the tournament and Nadal fail to reach the semis.
If Nadal fails to win even one round robin match, Djokovic could be crowned world No 1 simply by reaching the final after two group-stage wins.


Ray Parlour makes prediction about Tottenham’s Christian Eriksen
by Tom ProctertalkSPORT presenter Ray Parlour believes Christian Eriksen may try to block an exit in January.
The former Arsenal midfielder reckons he knows it would benefit himself financially to see out his contract, with his next club able to put more towards his wages as they’d save on a transfer fee.
The playmaker appears highly unlikely to agree a new deal with the club, and it is widely accepted he will be moving on.
Eriksen’s form has plunged this term and fans have often accused him of not wanting to be at the club amid his contract situation.
Parlour said: “I think the player will have something to say about [leaving in January], because he might say, ‘I’m not going anywhere’.
“From January 1 you can do your contract and pre-sign with whoever you are going to, and his wages will be so much more if he goes on a free transfer.
“So he’ll be saying: ‘No, I’m not going anywhere and I don’t have to go anywhere’.
“You might get £20 million for him in January, but that £20 million will go in his pocket if he stays another six months.”
TBR’s view – Tottenham will struggle to offload in January
Spurs will do extremely well to get rid of Eriksen in January.
At this point, it surely makes more sense for other teams to try and save money by signing him for the summer, perhaps on a pre-contract agreement.
At the moment, teams are unlikely to want to pay to have a player who is in such poor form.
And certainly if £75,000-a-week Eriksen (Spotrac) digs his heels in then there is very little chance of Tottenham shifting him for even a small fee.
Have something to tell us about this article?
Let us know


--- layout: default ---
This website is rarely updated and is very much a work in progress.
I am computational biologist / bioinformatician, interested in applying evolutionary and genetic variation techniques to understand and inform genomic health. I have extensive experience with working with population-scale genetic datasets.
A brief overview of my background can be found here.


[towns]________
Village
_________[towns]
[towns]_______
Kingdoms
________[towns]
[towns]______
Town-Zones
______[towns]
[towns]______
Seven-Signs
______[towns]
[towns]______
PvP-Arenas
______[towns]
[towns]______
Other-Areas
______[towns]


| Match | Prize | Odds |
|---|---|---|
|
+
|
Jackpot | 1 in 292,201,338 |
|
+
|
$1,000,000 | 1 in 11,688,053.52 |
|
+
|
$50,000 | 1 in 913,129.18 |
|
+
|
$100 | 1 in 36,525.17 |
|
+
|
$100 | 1 in 14,494.11 |
|
+
|
$7 | 1 in 579.76 |
|
+
|
$7 | 1 in 701.33 |
|
+
|
$4 | 1 in 91.98 |
|
+
|
$4 | 1 in 38.32 |
| Overall chance of winning any prize: | 1 in 24.87 |
*In California, prize payout amounts are pari-mutuel basis and determined by sales and the number of winners.
| Match | Your prize if the Power Play number is; | ||||
|---|---|---|---|---|---|
| 2 (24 in 43) |
3 (13 in 43) |
4 (3 in 43) |
5 (2 in 43) |
10 * (1 in 43) |
|
|
+
|
$2,000,000 | $2,000,000 | $2,000,000 | $2,000,000 | $2,000,000 |
|
+
|
$100,000 | $150,000 | $200,000 | $250,000 | $500,000 |
|
+
|
$200 | $300 | $400 | $500 | $1,000 |
|
+
|
$200 | $300 | $400 | $500 | $1,000 |
|
+
|
$14 | $21 | $28 | $35 | $70 |
|
+
|
$14 | $21 | $28 | $35 | $70 |
|
+
|
$8 | $12 | $16 | $20 | $40 |
|
+
|
$8 | $12 | $16 | $20 | $40 |
*The 10X multiplier is only in play when the advertised jackpot is $150 million or less.