cdemi's
22 December 2020 |
Software Development #Software #Dev #Programming |
Commits are snapshots, not diffs (github.blog) |
| Git has a reputation for being confusing. Users stumble over terminology and phrasing that misguides their expectations. This is most apparent in commands that “rewrite history” such as git cherry-pick or git rebase. ... Read more |
Get up to speed with partial clone and shallow clone (github.blog) |
| As your Git repositories grow, it becomes harder and harder for new developers to clone and start working on them. Git is designed as a distributed version control system. This means that you can work on your machine without needing a connection to a central server that controls how you interact with the repository. This is only fully realizable if you have all reachable data in your local repository.... Read more |
Architecture #SoftwareArchitecture #EnterpriseArchitecture |
Uber’s Real-Time Push Platform (eng.uber.com) |
| Uber builds multi-sided marketplaces handling millions of trips every day across the globe. We strive to build real-time experiences for all our users. The nature of real time marketplaces make them very lively. Over the course of a trip, there are multiple participants that can modify and view the state of an ongoing trip and need real-time updates. This creates the need to keep all active participants and apps synced with real-time information, whether it’s through pickup time, arrival time, and route lines on the screen, or nearby drivers when you open the app... Read more |
.NET #dotNet |
Should I use self-contained or framework-dependent publishing in Docker images? (andrewlock.net) ASP.NET Core Docker |
| In this post I compare the impact of the framework-dependent vs self-contained mode on Docker image size, taking layer caching into account... Read more |
What's next for System.Text.Json? (devblogs.microsoft.com) |
| Learn about the new performance, reliaility and easy adoption that has been made with System.Text.Json, and what’s going to come next.... Read more |
User Experience #UX |
How Discord Implemented App-Wide Keyboard Navigation (blog.discord.com) |
| We believe that Discord is for everyone — which is why we’ve been hard at work this year to improve the accessibility of our apps... Read more |
Data |
Introducing Confluent’s Parallel Consumer Message Processing Client (confluent.io) |
| Confluent's Parallel Consumer offers comprehensive parallel processing for significantly improved performance, lower latency, and scalability without adjusting partitions or managing more client instances.... Read more |
Kafka as a storage system (blog.twitter.com) |
| Kafka is traditionally used to power streaming infrastructures. Learn how we used Kafka as a storage system to build the Account Activity API Replay Feature.... Read more |
Optimizing data warehouse storage (netflixtechblog.com) |
| At Netflix, our current data warehouse contains hundreds of Petabytes of data stored in AWS S3, and each day we ingest and create additional Petabytes. At this scale, we can gain a significant amount of performance and cost benefits by optimizing the storage layout (records, objects, partitions) as the data lands into our warehouse.... Read more |
Security #InfoSec |
Bitwarden introduces 2021 Password Decisions Survey (bitwarden.com) |
| In a new survey, IT decision makers shed light on password management directions in the enterprise.... Read more |
Open Source #OSS #FOSS |
How we built the GitHub globe (github.blog) |
| GitHub is where the world builds software. More than 56 million developers around the world build and work together on GitHub. With our new homepage, we wanted to show how open source development transcends the borders we’re living in and to tell our product story through the lens of a developer’s journey.... Read more |
Quality Assurance #QA |
Reducing flaky builds by 18x (github.blog) |
| It’s four o’clock in the afternoon as you push the last tweak to your branch. Your teammate already reviewed and approved your pull request and now all that’s left is to wait for CI.  Surprised and a bit annoyed because the last five commits were green, you take a closer look only to find a failing test unrelated to your changes. When you run the test locally, it passes.... Read more |
A/B testing at LinkedIn: Assigning variants at scale (engineering.linkedin.com) |
| No matter how well-designed an infrastructure is, the ability to scale depends on an efficient and scientifically-valid variant assignment method. In this post, we will discuss a practical approach of making variant assignment blazing fast to handle trillions of invocations per day, as well as invariants and tricky parts of using such methods for online experiments.... Read more |
General Tech #Tech |
How an obscure British PC maker invented ARM and changed the world (arstechnica.com) |
| 1987's Acorn Archimedes was the first production RISC-based personal computer.... Read more |
Random |
To the brain, reading computer code is not the same as reading language (news.mit.edu) multiple demand network Evelina Fedorenko Anna Ivanova language processing computer science education reading code Scratch Python neuroscience of coding |
| MIT neuroscientists have found reading computer code does not rely on the regions of the brain involved in language processing. Instead, it activates the “multiple demand network,” which is also recruited for complex cognitive tasks such as solving math problems or crossword puzzles.... Read more |
|
This newsletter is made with 💖 by cdemi and sponsored by moo Research. You can find this MIT Licensed open-source project on GitHub cdemi/NewsletterCurator. Generated with version <IP_ADDRESS>. You can also find an archive of all sent newsletters on GitHub at https://newsletters.cdemi.io/. If you want to unsubscribe from this newsletter, please click here. If you're new and you want to subscribe to this newsletter, please click here. |


Class: Zif::Actions::Sequence
- Inherits:
-
Object
- Object
- Zif::Actions::Sequence
- Includes:
- Serializable
- Defined in:
- lib/zif/actions/sequence.rb
Overview
Inspired by developer.apple.com/documentation/spritekit/skaction
A sequence of Actions that can be repeated as a whole
Meant to be applied to an object using the Actionable mixin, just like Action
Instance Attribute Summary collapse
-
#action_index ⇒ Integer
readonly
Index of the current action for this sequence.
-
#callback ⇒ Proc
A callback to run at the end of the entire sequence.
-
#cur_repeat ⇒ Integer
The number of repeat iterations left.
-
#repeat ⇒ Integer
The number of times this Sequence should repeat.
-
#sub_actions ⇒ Array<Zif::Actions::Action>
The actions this sequence runs through.
-
#sub_repeats ⇒ Array<Integer>
readonly
The number of times each Action in #sub_actions should repeat before moving on.
1. Public Interface collapse
-
#complete? ⇒ Boolean
Has this sequence run out of repeat iterations?.
-
#cur_action ⇒ Zif::Actions::Action
The current Action in this sequence.
-
#initialize(actions, repeat: 1, &block) ⇒ Sequence
constructor
A new instance of Sequence.
-
#restart ⇒ Object
Resets the state of the sequence back to the initialized state.
2. Private-ish methods collapse
-
#next_action ⇒ Object
private
Advances the sequence to the next action.
-
#perform_callback ⇒ Object
private
Calls the #callback on
self
. -
#perform_tick ⇒ Boolean
private
Calls the current action’s Action#perform_tick Conditionally advances to the next action and performs the callback.
-
#reset_cur_action_repeat ⇒ Object
private
Resets the current action’s Action#repeat to the value it was initialized with.
-
#setup_action ⇒ Object
private
Resets the current action’s parameters, so it is fresh and ready to run.
Methods included from Serializable
#exclude_from_serialize, #inspect, #serialize, #to_s
Constructor Details
#initialize(actions, repeat: 1, &block) ⇒ Sequence
Returns a new instance of Sequence.
35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/zif/actions/sequence.rb', line 35 def initialize(actions, repeat: 1, &block) actions.each do |action| raise ArgumentError, "Invalid action: #{action}" unless action.is_a? Action end @callback = block if block_given? @sub_actions = actions @repeat = Action::REPEAT_NAMES[repeat] || repeat restart setup_action end |
Instance Attribute Details
#action_index ⇒ Integer (readonly)
Returns Index of the current action for this sequence.
12 13 14 |
# File 'lib/zif/actions/sequence.rb', line 12 def action_index @action_index end |
#callback ⇒ Proc
Returns A callback to run at the end of the entire sequence.
27 28 29 |
# File 'lib/zif/actions/sequence.rb', line 27 def callback @callback end |
#cur_repeat ⇒ Integer
Returns The number of repeat iterations left.
21 22 23 |
# File 'lib/zif/actions/sequence.rb', line 21 def cur_repeat @cur_repeat end |
#repeat ⇒ Integer
Returns The number of times this Sequence should repeat.
18 19 20 |
# File 'lib/zif/actions/sequence.rb', line 18 def repeat @repeat end |
#sub_actions ⇒ Array<Zif::Actions::Action>
Returns The actions this sequence runs through.
15 16 17 |
# File 'lib/zif/actions/sequence.rb', line 15 def sub_actions @sub_actions end |
#sub_repeats ⇒ Array<Integer> (readonly)
Returns The number of times each Action in #sub_actions should repeat before moving on.
24 25 26 |
# File 'lib/zif/actions/sequence.rb', line 24 def sub_repeats @sub_repeats end |
Instance Method Details
#complete? ⇒ Boolean
Returns Has this sequence run out of repeat iterations?.
62 63 64 65 |
# File 'lib/zif/actions/sequence.rb', line 62 def complete? # puts "Complete action! -<EMAIL_ADDRESS>if @repeat.zero? @cur_repeat.zero? end |
#cur_action ⇒ Zif::Actions::Action
Returns the current Action in this sequence.
57 58 59 |
# File 'lib/zif/actions/sequence.rb', line 57 def cur_action @sub_actions[@action_index] end |
#next_action ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Advances the sequence to the next action.
81 82 83 84 85 86 87 88 |
# File 'lib/zif/actions/sequence.rb', line 81 def next_action # puts "Sequence#next_action" reset_cur_action_repeat @action_index = (@action_index + 1) % @sub_actions.length @cur_repeat -= 1 if @action_index.zero? setup_action unless complete? end |
#perform_callback ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Calls the #callback on self
112 113 114 115 |
# File 'lib/zif/actions/sequence.rb', line 112 def perform_callback @callback.call(self) # puts "Sequence#perform_callback: Callback triggered" end |
#perform_tick ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Calls the current action’s Action#perform_tick Conditionally advances to the next action and performs the callback.
100 101 102 103 104 105 106 107 108 |
# File 'lib/zif/actions/sequence.rb', line 100 def perform_tick # puts "Sequence#perform_tick" @dirty = cur_action.perform_tick next_action if cur_action.complete? perform_callback if complete? && @callback @dirty end |
#reset_cur_action_repeat ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Resets the current action’s Action#repeat to the value it was initialized with.
92 93 94 |
# File 'lib/zif/actions/sequence.rb', line 92 def reset_cur_action_repeat cur_action.repeat = @sub_repeats[@action_index] end |
#restart ⇒ Object
Resets the state of the sequence back to the initialized state.
50 51 52 53 54 |
# File 'lib/zif/actions/sequence.rb', line 50 def restart @action_index = 0 @cur_repeat = @repeat @sub_repeats = @sub_actions.map(&:repeat).freeze end |
#setup_action ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Resets the current action’s parameters, so it is fresh and ready to run.
72 73 74 75 76 77 |
# File 'lib/zif/actions/sequence.rb', line 72 def setup_action # puts "Sequence#setup_action #{@action_index}" reset_cur_action_repeat cur_action.reset_start cur_action.reset_duration end |


Contribute¶
This guide will help you contribute to e.g. fix a bug or add a new feature for soa_driving.
Development Workflow¶
If you are a first-time contributor:
Go to https://github.com/cwfparsonson/soa_driving and click the “fork” button to create your own copy of the project.
Clone the project to your local computer:
git clone git@github.com:your-username/soa_driving.git
Navigate to the folder soa_driving and add the upstream repository:
git remote add upstream git@github.com:cwfparsonson/soa_driving.git
Now, you have remote repositories named:
upstream
, which refers to thesoa_driving
repositoryorigin
, which refers to your personal fork
Next, you need to set up your build environment. Here are instructions for two popular environment managers:
venv
(pip based)# Create a virtualenv named ``soa_driving-dev`` that lives in the directory of # the same name python -m venv soa_driving-dev # Activate it source soa_driving-dev/bin/activate # Install main development and runtime dependencies of soa_driving pip install -r <(cat requirements/{default,docs}.txt) # # These packages require that you have your system properly configured # and what that involves differs on various systems. # # In the soa_driving root directory folder, run python setup.py develop
conda
(Anaconda or Miniconda)# Create a conda environment named ``soa_driving-dev`` conda create --name soa_driving-dev # Activate it conda activate soa_driving-dev # Install main development and runtime dependencies of soa_driving conda install -c conda-forge `for i in requirements/{default,doc}.txt; do echo -n " --file $i "; done` # # These packages require that you have your system properly configured # and what that involves differs on various systems.  Since the branch name will appear in the merge message, use a sensible name such as ‘bugfix-for-issue-1480’:
git checkout -b bugfix-for-issue-1480
Commit locally as you progress (
git add
andgit commit
)
Submit your contribution:
Push your changes back to your fork on GitHub:
git push origin bugfix-for-issue-1480
Go to GitHub. The new branch will show up with a green Pull Request button—click it.
If you want, email<EMAIL_ADDRESS>to explain your changes or to ask for review.
Review process:
Your pull request will be reviewed.
To update your pull request, make your changes on your local repository and commit. As soon as those changes are pushed up (to the same branch as before) the pull request will update automatically.
Note
If the PR closes an issue, make sure that GitHub knows to automatically close the issue when the PR is merged. For example, if the PR closes issue number 1480, you could use the phrase “Fixes #1480” in the PR description or commit message.
Document changes
If your change introduces any API modifications, please update
doc/release/release_dev.rst
.If your hange introduces a deprecation, add a reminder to
doc/developer/deprecations.rst
for the team to remove the deprecated functionality in the future.Note
To reviewers: make sure the merge message has a brief description of the change(s) and if the PR closes an issue add, for example, “Closes #123” where 123 is the issue number.
Divergence from upstream master
¶
If GitHub indicates that the branch of your Pull Request can no longer be merged automatically, merge the master branch into yours:
git fetch upstream master
git merge upstream/master
If any conflicts occur, they need to be fixed before continuing. See which files are in conflict using:
git status
Which displays a message like:
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: file_with_conflict.txt
Inside the conflicted file, you’ll find sections like these:
<<<<<<< HEAD
The way the text looks in your branch
=======
The way the text looks in the master branch
>>>>>>> master
Choose one version of the text that should be kept, and delete the rest:
The way the text looks in your branch
Now, add the fixed file:
git add file_with_conflict.txt
Once you’ve fixed all merge conflicts, do:
git commit
c


| Interface | Description |
|---|---|
| Report |
Represents a business report.
|
| ReportRunner<T extends ReportTemplate> |
Runs a report for a specific template type.
|
| ReportTemplate |
Marker interface for report templates.
|
| ReportTemplateIniLoader<T extends ReportTemplate> |
Loads a report template from an ini-based file format.
|
| Class | Description |
|---|---|
| ReportCalculationResults |
Stores a set of engine calculation results along with the context required to run reports.
|
| ReportCalculationResults.Meta |
The meta-bean for
ReportCalculationResults . |
| ReportRequirements |
Describes the requirements for a report to be run in terms of trade-level measures that
can be separately obtained by the calculation engine.
|
| ReportRequirements.Meta |
The meta-bean for
ReportRequirements . |
Reports are generated using a report template and a set of calculation results. A report contains a table of data where the rows are the inputs to the calculations, for example trades, and the columns contain data from the calculation results or the trades.
The first section of the .ini file defines the settings for the report. Currently this only contains the type of the report:
[Settings] reportType = tradeThe report columns are defined by the remaining sections in the .ini file. The section header defines the column name and the
value
attribute is an expression defining the value in the column. The following
snippet from a trade report for FRA trades defines three columns: Settlement Date, Index and Par Rate.
[Settlement Date] value = Trade.settlementDate [Index] value = Product.index.name [Par Rate] value = Measures.ParRateThe
value
expression is consists of multiple sections separated by dots. The first section specifies
the object which is the source of the data in the column. The supported values are:
trade
or
trade info
security
or
security info
position
or
position info
calculation target
product
associated with
the trade. This is only applicable if the trade implements
ProductTrade
Product.index.name
' and the results contain
FraTrade
instances
the following calls will be made for each trade in the results:
The cell in the report will contain name of the index referenced by the FRA.Copyright 2009-Present by OpenGamma Inc. and individual contributors
Apache v2 licensed
Additional documentation can be found at opengamma.github.io/StrataDocs.


{% extends "base.html" %} {% block title %}Page Not Found{% endblock %} {% block content %}
That page doesn't even exist.


Mixology Demos
- Hello - simple sender and receiver
- Controls - mix with data channel
- Mix3 - three nodes, mixing two cameras; note: install Chrome extension (Mixmit) before running
- Sender (open two instances, preferably on different machines)
- Mix (start Mixmit Chrome extension after loading page)
- Viewer


{% extends "layout.html" %}
{% block content %}
{{ league.get_name() }} Players
Click on the player's home page to see their league stats, their games, subscribe to their list escrow, etc.
| Tier | Division | Player Home Page | Number of Games Played |
|---|---|---|---|
| {{ p.tier.get_name() }} | {{ p.division.get_name() }} | {{ p.get_url() }} | {{ p.num_games_played() }} |


Monochrome/Colors
Switch to monochrome: the layout is drawn in black and white. This type of drawing is convenient to build monochrome documentation. Press "Alt"+"Print Screen" to copy the screen to the clipboard. Then, open "Word", click "Edit-> Paste". The screen is inserted into the document.
[Back]


'They meant the world to me' - families grieve as KZN storm claims 3
by Kaveel SinghA Durban family is struggling to come to terms with the death of their parents following heavy storms in and around the city on Monday.
Amaoti couple Nomathamsanqa Nyangule, 55, and Simangaliso Zondo, 69, died after the roof and wall of their house collapsed on them at around 21:00 on Monday.
Also on Monday in rural KwaZulu-Natal, an Okhahlamba woman, 24-year-old Sthembile Zimba, was killed following a lightning strike, Cooperative Governance and Traditional Affairs MEC Sipho Hlomuka said.
Speaking to journalists outside their devastated home, the couple's daughter, Zilungile Nyangule, 19, said she was at a loss for words after her parents' death.
"We were so close. They meant the world to me. We loved each other. I don't know what to say because we were so close."
Nyangule said they were asleep when the family woke to a loud bang.
"It was around 21:00, my sister and I were sleeping. I heard a noise and woke up and came to the sitting room and saw the walls on top of my parents. We called the community to help, which they did, but [my parents] were dead."
Durban Mayor Mxolisi Kaunda sent his condolences to the family.
"We have visited the family and passed on our heartfelt condolences. We pledge our support for them during this difficult period," Kaunda said.

"We have put together a team from all units led by disaster management so we can deal with the damage. In some areas bridges have collapsed, and roads developed sinkholes."
Thunderstorms
Hlomuka called on residents residing in low-lying areas to seek shelter on higher ground.
"We are urging residents to be extremely cautious as severe thunderstorms [are expected]."
He said the northern areas of the province - which include uThukela, Mzinyathi, Amajuba and Zululand district municipalities - could be affected.
"Our teams are on the ground and we are urging residents to be cautious and to double-check the weather forecast before making any long journeys. We appeal to parents and teachers to ensure that scholars utilise proper routes going to and coming back from schools."


Bootstrapifier
GitHub Repo
Guidelines
No need to include any classes or id's for it to work
No need to include/link Bootstrap, it will for you
It will add the classes alongside existing ones, which could cause CSS interference
It will preserve scripts and comments
Simply copy your HTML, and click the "Parse & Replace Clipboard" button. Alternatively, paste it in the HTML Input text area, then parse and copy it
Copy/Paste buttons may be disabled if your browser does not support clipboard usage
Options
Wrap body contents with container?
Apply list groups and list group items to lists (ul, ol, li)?
Center list groups at 50% width? (adds "w-50", "ml-auto", and "mr-auto" classes to "ol" and "ul")
Apply basic dark theme to body? Note that this is not Bootstrap. Details on repo.
Element tags to wrap with row (csv):
Element tags to add text-center class (csv):
HTML Input
HTML Output


[1]
worked for basic requirements like maps quick googling etc.
[2]
something you ca n't pre-plan but it just worked out perfectly.


{{message}}
Great! There are no debts. Everything's settled up.
The algorithm we use minimizes the amount of payments needed to settle the group up. How do we do this?
Let's say you have a group of friends, Tony, Sara and Simon. Tony owes 20 to Sara and Sara owes 20 to Simon
Settling this up the traditional way would suggest that Tony pays 20 to Sara and Sara pays 20 to Simon. This takes two transactions.
But this can be short-circuited. If you think about it, Sara needs the 20 from Tony just to pay Simon. This is where we step in and suggest another route instead. Instead of two transactions, we simplify this to one transaction, from Tony to Simon.


Painless Guide
Painless is a simple, secure scripting language. It is the default scripting language for OpenSearch and can safely be used for inline and stored scripts. For a jump start into Painless, see A Brief Painless Walkthrough. For a detailed description of the Painless syntax and language features, see the Painless Language Specification.
You can use Painless anywhere scripts are used in OpenSearch. Painless provides:
-
Fast performance: Painless scripts run several times faster than the alternatives.
-
Safety: Fine-grained allowlist with method call/field granularity. See the Painless API Reference for a complete list of available classes and methods.
-
Optional typing: Variables and parameters can use explicit types or the dynamic
def
type. -
Syntax: Extends a subset of Java’s syntax to provide additional scripting language features.
-
Optimizations: Designed specifically for OpenSearch scripting.
A Brief Painless Walkthrough
To illustrate how Painless works, let’s load some hockey stats into an OpenSearch index:
PUT hockey/_bulk?refresh
{"index":{"_id":1}}
{"first":"johnny","last":"gaudreau","goals":[9,27,1],"assists":[17,46,0],"gp":[26,82,1],"born":"1993/08/13"}
{"index":{"_id":2}}
{"first":"sean","last":"monohan","goals":[7,54,26],"assists":[11,26,13],"gp":[26,82,82],"born":"1994/10/12"}
{"index":{"_id":3}}
{"first":"jiri","last":"hudler","goals":[5,34,36],"assists":[11,62,42],"gp":[24,80,79],"born":"1984/01/04"}
{"index":{"_id":4}}
{"first":"micheal","last":"frolik","goals":[4,6,15],"assists":[8,23,15],"gp":[26,82,82],"born":"1988/02/17"}
{"index":{"_id":5}}
{"first":"sam","last":"bennett","goals":[5,0,0],"assists":[8,1,0],"gp":[26,1,0],"born":"1996/06/20"}
{"index":{"_id":6}}
{"first":"dennis","last":"wideman","goals":[0,26,15],"assists":[11,30,24],"gp":[26,81,82],"born":"1983/03/20"}
{"index":{"_id":7}}
{"first":"david","last":"jones","goals":[7,19,5],"assists":[3,17,4],"gp":[26,45,34],"born":"1984/08/10"}
{"index":{"_id":8}}
{"first":"tj","last":"brodie","goals":[2,14,7],"assists":[8,42,30],"gp":[26,82,82],"born":"1990/06/07"}
{"index":{"_id":39}}
{"first":"mark","last":"giordano","goals":[6,30,15],"assists":[3,30,24],"gp":[26,60,63],"born":"1983/10/03"}
{"index":{"_id":10}}
{"first":"mikael","last":"backlund","goals":[3,15,13],"assists":[6,24,18],"gp":[26,82,82],"born":"1989/03/17"}
{"index":{"_id":11}}
{"first":"joe","last":"colborne","goals":[3,18,13],"assists":[6,20,24],"gp":[26,67,82],"born":"1990/01/30"}
Accessing Doc Values from Painless
Document values can be accessed from a Map
named doc
.
For example, the following script calculates a player’s total goals. This example uses a strongly typed int
and a for
loop.
GET hockey/_search
{
"query": {
"function_score": {
"script_score": {
"script": {
"lang": "painless",
"source": """
int total = 0;
for (int i = 0; i < doc['goals'].length; ++i) {
total += doc['goals'][i];
}
return total;
"""
}
}
}
}
}
Alternatively, you could do the same thing using a script field instead of a function score:
GET hockey/_search
{
"query": {
"match_all": {}
},
"script_fields": {
"total_goals": {
"script": {
"lang": "painless",
"source": """
int total = 0;
for (int i = 0; i < doc['goals'].length; ++i) {
total += doc['goals'][i];
}
return total;
"""
}
}
}
}
The following example uses a Painless script to sort the players by their combined first and last names. The names are accessed using
doc['first'].value
and doc['last'].value
.
GET hockey/_search
{
"query": {
"match_all": {}
},
"sort": {
"_script": {
"type": "string",
"order": "asc",
"script": {
"lang": "painless",
"source": "doc['first.keyword'].value + ' ' + doc['last.keyword'].value"
}
}
}
}
Missing values
doc['field'].value
throws an exception if
the field is missing in a document.
To check if a document is missing a value, you can call
doc['field'].size() == 0
.
Updating Fields with Painless
You can also easily update fields. You access the original source for a field as ctx._source.<field-name>
.
First, let’s look at the source data for a player by submitting the following request:
GET hockey/_search
{
"query": {
"term": {
"_id": 1
}
}
}
To change player 1’s last name to hockey
, simply set ctx._source.last
to the new value:
POST hockey/_update/1
{
"script": {
"lang": "painless",
"source": "ctx._source.last = params.last",
"params": {
"last": "hockey"
}
}
}
You can also add fields to a document. For example, this script adds a new field that contains the player’s nickname, hockey.
POST hockey/_update/1
{
"script": {
"lang": "painless",
"source": """
ctx._source.last = params.last;
ctx._source.nick = params.nick
""",
"params": {
"last": "gaudreau",
"nick": "hockey"
}
}
}
Dates
Date fields are exposed as
ZonedDateTime
, so they support methods like getYear
, getDayOfWeek
or e.g. getting milliseconds since epoch with getMillis
. To use these
in a script, leave out the get
prefix and continue with lowercasing the
rest of the method name. For example, the following returns every hockey
player’s birth year:
GET hockey/_search
{
"script_fields": {
"birth_year": {
"script": {
"source": "doc.born.value.year"
}
}
}
}
Regular expressions
|
Note
|
Regexes are enabled by default as the Setting script.painless.regex.enabled
has a new option, limited , the default. This defaults to using regular expressions
but limiting the complexity of the regular expressions. Innocuous looking regexes
can have staggering performance and stack depth behavior. But still, they remain an
amazingly powerful tool. In addition, to limited , the setting can be set to true ,
as before, which enables regular expressions without limiting them.To enable them
yourself set script.painless.regex.enabled: true in opensearch.yml .
|
Painless’s native support for regular expressions has syntax constructs:
-
/pattern/
: Pattern literals create patterns. This is the only way to create a pattern in painless. The pattern inside the /'s are just Java regular expressions. See Pattern flags for more. -
=~
: The find operator return aboolean
,true
if a subsequence of the text matches,false
otherwise. -
==~
: The match operator returns aboolean
,true
if the text matches,false
if it doesn’t.
Using the find operator (=~
) you can update all hockey players with "b" in
their last name:
POST hockey/_update_by_query
{
"script": {
"lang": "painless",
"source": """
if (ctx._source.last =~ /b/) {
ctx._source.last += "matched";
} else {
ctx.op = "noop";
}
"""
}
}
Using the match operator (==~
) you can update all the hockey players whose
names start with a consonant and end with a vowel:
POST hockey/_update_by_query
{
"script": {
"lang": "painless",
"source": """
if (ctx._source.last ==~ /[^aeiou].*[aeiou]/) {
ctx._source.last += "matched";
} else {
ctx.op = "noop";
}
"""
}
}
You can use the Pattern.matcher
directly to get a Matcher
instance and
remove all of the vowels in all of their last names:
POST hockey/_update_by_query
{
"script": {
"lang": "painless",
"source": "ctx._source.last = /[aeiou]/.matcher(ctx._source.last).replaceAll('')"
}
}
Matcher.replaceAll
is just a call to Java’s Matcher’s
replaceAll
method so it supports `$1
and \1
for replacements:
POST hockey/_update_by_query
{
"script": {
"lang": "painless",
"source": "ctx._source.last = /n([aeiou])/.matcher(ctx._source.last).replaceAll('$1')"
}
}
If you need more control over replacements you can call replaceAll
on a
CharSequence
with a Function<Matcher, String>
that builds the replacement.
This does not support $1
or \1
to access replacements because you already
have a reference to the matcher and can get them with m.group(1)
.
|
Important
|
Calling Matcher.find inside of the function that builds the
replacement is rude and will likely break the replacement process.
|
This will make all of the vowels in the hockey player’s last names upper case:
POST hockey/_update_by_query
{
"script": {
"lang": "painless",
"source": """
ctx._source.last = ctx._source.last.replaceAll(/[aeiou]/, m ->
m.group().toUpperCase(Locale.ROOT))
"""
}
}
Or you can use the CharSequence.replaceFirst
to make the first vowel in their
last names upper case:
POST hockey/_update_by_query
{
"script": {
"lang": "painless",
"source": """
ctx._source.last = ctx._source.last.replaceFirst(/[aeiou]/, m ->
m.group().toUpperCase(Locale.ROOT))
"""
}
}
Note: all of the _update_by_query
examples above could really do with a
query
to limit the data that they pull back. While you could use a
script query it wouldn’t be as efficient
as using any other query because script queries aren’t able to use the inverted
index to limit the documents that they have to check.
Using Datetime in Painless
Datetime API
Datetimes in Painless use the standard Java libraries and are available through the Painless Shared API. Most of the classes from the following Java packages are available to use in Painless scripts:
Datetime Representation
Datetimes in Painless are most commonly represented as a numeric value, a string value, or a complex value.
- numeric
-
a datetime representation as a number from a starting offset called an epoch; in Painless this is typically a long as milliseconds since an epoch of 1970-01-01 00:00:00 Zulu Time
- string
-
a datetime representation as a sequence of characters defined by a standard format or a custom format; in Painless this is typically a String of the standard format ISO 8601
- complex
-
a datetime representation as a complex type (object) that abstracts away internal details of how the datetime is stored and often provides utilities for modification and comparison; in Painless this is typically a ZonedDateTime
Switching between different representations of datetimes is often necessary to achieve a script’s objective(s). A typical pattern in a script is to switch a numeric or string datetime to a complex datetime, modify or compare the complex datetime, and then switch it back to a numeric or string datetime for storage or to return a result.
Datetime Parsing and Formatting
Datetime parsing is a switch from a string datetime to a complex datetime, and datetime formatting is a switch from a complex datetime to a string datetime.
A DateTimeFormatter is a complex type (object) that defines the allowed sequence of characters for a string datetime. Datetime parsing and formatting often require a DateTimeFormatter. For more information about how to use a DateTimeFormatter see the Java documentation.
Datetime Parsing Examples
-
parse from milliseconds
String milliSinceEpochString = "434931330000"; long milliSinceEpoch = Long.parseLong(milliSinceEpochString); Instant instant = Instant.ofEpochMilli(milliSinceEpoch); ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
-
parse from ISO 8601
String datetime = '1983-10-13T22:15:30Z'; ZonedDateTime zdt = ZonedDateTime.parse(datetime); (1)
-
Note the parse method uses ISO 8601 by default.
-
-
parse from RFC 1123
String datetime = 'Thu, 13 Oct 1983 22:15:30 GMT'; ZonedDateTime zdt = ZonedDateTime.parse(datetime, DateTimeFormatter.RFC_1123_DATE_TIME); (1)
-
Note the use of a built-in DateTimeFormatter.
-
-
parse from a custom format
String datetime = 'custom y 1983 m 10 d 13 22:15:30 Z'; DateTimeFormatter dtf = DateTimeFormatter.ofPattern( "'custom' 'y' yyyy 'm' MM 'd' dd HH:mm:ss VV"); ZonedDateTime zdt = ZonedDateTime.parse(datetime, dtf); (1)
-
Note the use of a custom DateTimeFormatter.
-
Datetime Formatting Examples
-
format to ISO 8601
ZonedDateTime zdt = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z')); String datetime = zdt.format(DateTimeFormatter.ISO_INSTANT); (1)
-
Note the use of a built-in DateTimeFormatter.
-
-
format to a custom format
ZonedDateTime zdt = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z')); DateTimeFormatter dtf = DateTimeFormatter.ofPattern( "'date:' yyyy/MM/dd 'time:' HH:mm:ss"); String datetime = zdt.format(dtf); (1)
-
Note the use of a custom DateTimeFormatter.
-
Datetime Conversion
Datetime conversion is a switch from a numeric datetime to a complex datetime and vice versa.
Datetime Conversion Examples
-
convert from milliseconds
long milliSinceEpoch =<PHONE_NUMBER>00L; Instant instant = Instant.ofEpochMilli(milliSinceEpoch); ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
-
convert to milliseconds
ZonedDateTime zdt = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z')); long milliSinceEpoch = zdt.toInstant().toEpochMilli();
Datetime Pieces
Datetime representations often contain the data to extract individual datetime pieces such as year, hour, timezone, etc. Use individual pieces of a datetime to create a complex datetime, and use a complex datetime to extract individual pieces.
Datetime Pieces Examples
-
create a complex datetime from pieces
int year = 1983; int month = 10; int day = 13; int hour = 22; int minutes = 15; int seconds = 30; int nanos = 0; ZonedDateTime zdt = ZonedDateTime.of( year, month, day, hour, minutes, seconds, nanos, ZoneId.of('Z'));
-
extract pieces from a complex datetime
ZonedDateTime zdt = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 100, ZoneId.of(tz)); int year = zdt.getYear(); int month = zdt.getMonthValue(); int day = zdt.getDayOfMonth(); int hour = zdt.getHour(); int minutes = zdt.getMinute(); int seconds = zdt.getSecond(); int nanos = zdt.getNano();
Datetime Modification
Use either a numeric datetime or a complex datetime to do modification such as adding several seconds to a datetime or subtracting several days from a datetime. Use standard numeric operators to modify a numeric datetime. Use methods (or fields) to modify a complex datetime. Note many complex datetimes are immutable so upon modification a new complex datetime is created that requires assignment or immediate use.
Datetime Modification Examples
-
Subtract three seconds from a numeric datetime in milliseconds
long milliSinceEpoch =<PHONE_NUMBER>00L; milliSinceEpoch = milliSinceEpoch - 1000L*3L;
-
Add three days to a complex datetime
ZonedDateTime zdt = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z')); ZonedDateTime updatedZdt = zdt.plusDays(3);
-
Subtract 125 minutes from a complex datetime
ZonedDateTime zdt = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z')); ZonedDateTime updatedZdt = zdt.minusMinutes(125);
-
Set the year on a complex datetime
ZonedDateTime zdt = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z')); ZonedDateTime updatedZdt = zdt.withYear(1976);
Datetime Difference (Elapsed Time)
Use either two numeric datetimes or two complex datetimes to calculate the difference (elapsed time) between two different datetimes. Use subtraction to calculate the difference between two numeric datetimes of the same time unit such as milliseconds. For complex datetimes there is often a method or another complex type (object) available to calculate the difference. Use ChronoUnit to calculate the difference between two complex datetimes if supported.
Datetime Difference Examples
-
Difference in milliseconds between two numeric datetimes
long startTimestamp =<PHONE_NUMBER>00L; long endTimestamp =<PHONE_NUMBER>00L; long differenceInMillis = endTimestamp - startTimestamp;
-
Difference in milliseconds between two complex datetimes
ZonedDateTime zdt1 = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 11000000, ZoneId.of('Z')); ZonedDateTime zdt2 = ZonedDateTime.of(1983, 10, 13, 22, 15, 35, 0, ZoneId.of('Z')); long differenceInMillis = ChronoUnit.MILLIS.between(zdt1, zdt2);
-
Difference in days between two complex datetimes
ZonedDateTime zdt1 = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 11000000, ZoneId.of('Z')); ZonedDateTime zdt2 = ZonedDateTime.of(1983, 10, 17, 22, 15, 35, 0, ZoneId.of('Z')); long differenceInDays = ChronoUnit.DAYS.between(zdt1, zdt2);
Datetime Comparison
Use either two numeric datetimes or two complex datetimes to do a datetime comparison. Use standard comparison operators to compare two numeric datetimes of the same time unit such as milliseconds. For complex datetimes there is often a method or another complex type (object) available to do the comparison.
Datetime Comparison Examples
-
Greater than comparison of two numeric datetimes in milliseconds
long timestamp1 =<PHONE_NUMBER>00L; long timestamp2 =<PHONE_NUMBER>00L; if (timestamp1 > timestamp2) { // handle condition }
-
Equality comparison of two complex datetimes
ZonedDateTime zdt1 = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z')); ZonedDateTime zdt2 = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z')); if (zdt1.equals(zdt2)) { // handle condition }
-
Less than comparison of two complex datetimes
ZonedDateTime zdt1 = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z')); ZonedDateTime zdt2 = ZonedDateTime.of(1983, 10, 17, 22, 15, 35, 0, ZoneId.of('Z')); if (zdt1.isBefore(zdt2)) { // handle condition }
-
Greater than comparison of two complex datetimes
ZonedDateTime zdt1 = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z')); ZonedDateTime zdt2 = ZonedDateTime.of(1983, 10, 17, 22, 15, 35, 0, ZoneId.of('Z')); if (zdt1.isAfter(zdt2)) { // handle condition }
Datetime Zone
Both string datetimes and complex datetimes have a timezone with a default of
UTC
. Numeric datetimes do not have enough explicit information to
have a timezone, so UTC
is always assumed. Use
methods (or fields) in
conjunction with a ZoneId to change
the timezone for a complex datetime. Parse a string datetime into a complex
datetime to change the timezone, and then format the complex datetime back into
a desired string datetime. Note many complex datetimes are immutable so upon
modification a new complex datetime is created that requires
assignment or immediate use.
Datetime Zone Examples
-
Modify the timezone for a complex datetime
ZonedDateTime utc = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z')); ZonedDateTime pst = utc.withZoneSameInstant(ZoneId.of('America/Los_Angeles'));
-
Modify the timezone for a string datetime
String gmtString = 'Thu, 13 Oct 1983 22:15:30 GMT'; ZonedDateTime gmtZdt = ZonedDateTime.parse(gmtString, DateTimeFormatter.RFC_1123_DATE_TIME); (1) ZonedDateTime pstZdt = gmtZdt.withZoneSameInstant(ZoneId.of('America/Los_Angeles')); String pstString = pstZdt.format(DateTimeFormatter.RFC_1123_DATE_TIME);
-
Note the use of a built-in DateTimeFormatter.
-
Datetime Input
There are several common ways datetimes are used as input for a script determined by the Painless context. Typically, datetime input will be accessed from parameters specified by the user, from an original source document, or from an indexed document.
Datetime Input From User Parameters
Use the params section
during script specification to pass in a numeric datetime or string datetime as
a script input. Access to user-defined parameters within a script is dependent
on the Painless context, though, the parameters are most commonly accessible
through an input called params
.
Examples
-
Parse a numeric datetime from user parameters to a complex datetime
-
Input:
... "script": { ... "params": { "input_datetime":<PHONE_NUMBER>00 } } ...
-
Script:
long inputDateTime = params['input_datetime']; Instant instant = Instant.ofEpochMilli(inputDateTime); ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
-
-
Parse a string datetime from user parameters to a complex datetime
-
Input:
... "script": { ... "params": { "input_datetime": "custom y 1983 m 10 d 13 22:15:30 Z" } } ...
-
Script:
String datetime = params['input_datetime']; DateTimeFormatter dtf = DateTimeFormatter.ofPattern( "'custom' 'y' yyyy 'm' MM 'd' dd HH:mm:ss VV"); ZonedDateTime zdt = ZonedDateTime.parse(datetime, dtf); (1)
-
Note the use of a custom DateTimeFormatter.
-
-
Datetime Input From a Source Document
Use an original source document as a script
input to access a numeric datetime or string datetime for a specific field
within that document. Access to an original source document within a script is
dependent on the Painless context and is not always available. An original
source document is most commonly accessible through an input called
ctx['_source']
or params['_source']
.
Examples
-
Parse a numeric datetime from a sourced document to a complex datetime
-
Input:
{ ... "input_datetime":<PHONE_NUMBER>00 ... }
-
Script:
long inputDateTime = ctx['_source']['input_datetime']; (1) Instant instant = Instant.ofEpochMilli(inputDateTime); ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
-
Note access to
_source
is dependent on the Painless context.
-
-
-
Parse a string datetime from a sourced document to a complex datetime
-
Input:
{ ... "input_datetime": "1983-10-13T22:15:30Z" ... }
-
Script:
String datetime = params['_source']['input_datetime']; (1) ZonedDateTime zdt = ZonedDateTime.parse(datetime); (2)
-
Note access to
_source
is dependent on the Painless context. -
Note the parse method uses ISO 8601 by default.
-
-
Datetime Input From an Indexed Document
Use an indexed document as a script input to access a complex datetime for a
specific field within that document where the field is mapped as a
standard date or a nanosecond date.
Numeric datetime fields mapped as numeric and string
datetime fields mapped as keyword are accessible through an
indexed document as well. Access to an indexed document within a script is
dependent on the Painless context and is not always available. An indexed
document is most commonly accessible through an input called doc
.
Examples
-
Format a complex datetime from an indexed document to a string datetime
-
Assumptions:
-
The field
input_datetime
exists in all indexes as part of the query -
All indexed documents contain the field
input_datetime
-
-
Mappings:
{ "mappings": { ... "properties": { ... "input_datetime": { "type": "date" } ... } ... } }
-
Script:
ZonedDateTime input = doc['input_datetime'].value; String output = input.format(DateTimeFormatter.ISO_INSTANT); (1)
-
Note the use of a built-in DateTimeFormatter.
-
-
-
Find the difference between two complex datetimes from an indexed document
-
Assumptions:
-
The fields
start
andend
may not exist in all indexes as part of the query -
The fields
start
andend
may not have values in all indexed documents
-
-
Mappings:
{ "mappings": { ... "properties": { ... "start": { "type": "date" }, "end": { "type": "date" } ... } ... } }
-
Script:
if (doc.containsKey('start') && doc.containsKey('end')) { (1) if (doc['start'].size() > 0 && doc['end'].size() > 0) { (2) ZonedDateTime start = doc['start'].value; ZonedDateTime end = doc['end'].value; long differenceInMillis = ChronoUnit.MILLIS.between(start, end); // handle difference in times } else { // handle fields without values } } else { // handle index with missing fields }
-
When a query’s results span multiple indexes, some indexes may not contain a specific field. Use the
containsKey
method call on thedoc
input to ensure a field exists as part of the index for the current document. -
Some fields within a document may have no values. Use the
size
method call on a field within thedoc
input to ensure that field has at least one value for the current document.
-
-
Datetime Now
Under most Painless contexts the current datetime, now
, is not supported.
There are two primary reasons for this. The first is that scripts are often run once
per document, so each time the script is run a different now
is returned. The
second is that scripts are often run in a distributed fashion without a way to
appropriately synchronize now
. Instead, pass in a user-defined parameter with
either a string datetime or numeric datetime for now
. A numeric datetime is
preferred as there is no need to parse it for comparison.
Datetime Now Examples
-
Use a numeric datetime as
now
-
Assumptions:
-
The field
input_datetime
exists in all indexes as part of the query -
All indexed documents contain the field
input_datetime
-
-
Mappings:
{ "mappings": { ... "properties": { ... "input_datetime": { "type": "date" } ... } ... } }
-
Input:
... "script": { ... "params": { "now": <generated numeric datetime in milliseconds since epoch> } } ...
-
Script:
long now = params['now']; ZonedDateTime inputDateTime = doc['input_datetime']; long millisDateTime = zdt.toInstant().toEpochMilli(); long elapsedTime = now - millisDateTime;
-
-
Use a string datetime as
now
-
Assumptions:
-
The field
input_datetime
exists in all indexes as part of the query -
All indexed documents contain the field
input_datetime
-
-
Mappings:
{ "mappings": { ... "properties": { ... "input_datetime": { "type": "date" } ... } ... } }
-
Input:
... "script": { ... "params": { "now": "<generated string datetime in ISO-8601>" } } ...
-
Script:
String nowString = params['now']; ZonedDateTime nowZdt = ZonedDateTime.parse(nowString); (1) long now = ZonedDateTime.toInstant().toEpochMilli(); ZonedDateTime inputDateTime = doc['input_datetime']; long millisDateTime = zdt.toInstant().toEpochMilli(); long elapsedTime = now - millisDateTime;
-
Note this parses the same string datetime every time the script runs. Use a numeric datetime to avoid a significant performance hit.
-
-
Datetime Examples in Contexts
Load the Example Data
Run the following curl commands to load the data necessary for the context examples into an OpenSearch cluster:
-
Create mappings for the sample data.
PUT /messages { "mappings": { "properties": { "priority": { "type": "integer" }, "datetime": { "type": "date" }, "message": { "type": "text" } } } }
-
Load the sample data.
POST /_bulk { "index" : { "_index" : "messages", "_id" : "1" } } { "priority": 1, "datetime": "2019-07-17T12:13:14Z", "message": "m1" } { "index" : { "_index" : "messages", "_id" : "2" } } { "priority": 1, "datetime": "2019-07-24T01:14:59Z", "message": "m2" } { "index" : { "_index" : "messages", "_id" : "3" } } { "priority": 2, "datetime": "1983-10-14T00:36:42Z", "message": "m3" } { "index" : { "_index" : "messages", "_id" : "4" } } { "priority": 3, "datetime": "1983-10-10T02:15:15Z", "message": "m4" } { "index" : { "_index" : "messages", "_id" : "5" } } { "priority": 3, "datetime": "1983-10-10T17:18:19Z", "message": "m5" } { "index" : { "_index" : "messages", "_id" : "6" } } { "priority": 1, "datetime": "2019-08-03T17:19:31Z", "message": "m6" } { "index" : { "_index" : "messages", "_id" : "7" } } { "priority": 3, "datetime": "2019-08-04T17:20:00Z", "message": "m7" } { "index" : { "_index" : "messages", "_id" : "8" } } { "priority": 2, "datetime": "2019-08-04T18:01:01Z", "message": "m8" } { "index" : { "_index" : "messages", "_id" : "9" } } { "priority": 3, "datetime": "1983-10-10T19:00:45Z", "message": "m9" } { "index" : { "_index" : "messages", "_id" : "10" } } { "priority": 2, "datetime": "2019-07-23T23:39:54Z", "message": "m10" }
Day-of-the-Week Bucket Aggregation Example
The following example uses a terms aggregation as part of the bucket script aggregation context to display the number of messages from each day-of-the-week.
GET /messages/_search?pretty=true
{
"aggs": {
"day-of-week-count": {
"terms": {
"script": "return doc[\"datetime\"].value.getDayOfWeekEnum();"
}
}
}
}
Morning/Evening Bucket Aggregation Example
The following example uses a terms aggregation as part of the bucket script aggregation context to display the number of messages received in the morning versus the evening.
GET /messages/_search?pretty=true
{
"aggs": {
"am-pm-count": {
"terms": {
"script": "return doc[\"datetime\"].value.getHour() < 12 ? \"AM\" : \"PM\";"
}
}
}
}
Age of a Message Script Field Example
The following example uses a script field as part of the field context to display the elapsed time between "now" and when a message was received.
GET /_search?pretty=true
{
"query": {
"match_all": {}
},
"script_fields": {
"message_age": {
"script": {
"source": "ZonedDateTime now = ZonedDateTime.ofInstant(Instant.ofEpochMilli(params[\"now\"]), ZoneId.of(\"Z\")); ZonedDateTime mdt = doc[\"datetime\"].value; String age; long years = mdt.until(now, ChronoUnit.YEARS); age = years + \"Y \"; mdt = mdt.plusYears(years); long months = mdt.until(now, ChronoUnit.MONTHS); age += months + \"M \"; mdt = mdt.plusMonths(months); long days = mdt.until(now, ChronoUnit.DAYS); age += days + \"D \"; mdt = mdt.plusDays(days); long hours = mdt.until(now, ChronoUnit.HOURS); age += hours + \"h \"; mdt = mdt.plusHours(hours); long minutes = mdt.until(now, ChronoUnit.MINUTES); age += minutes + \"m \"; mdt = mdt.plusMinutes(minutes); long seconds = mdt.until(now, ChronoUnit.SECONDS); age += hours + \"s\"; return age;",
"params": {
"now":<PHONE_NUMBER>830
}
}
}
}
}
The following shows the script broken into multiple lines:
ZonedDateTime now = ZonedDateTime.ofInstant(
Instant.ofEpochMilli(params['now']), ZoneId.of('Z')); (1)
ZonedDateTime mdt = doc['datetime'].value; (2)
String age;
long years = mdt.until(now, ChronoUnit.YEARS); (3)
age = years + 'Y '; (4)
mdt = mdt.plusYears(years); (5)
long months = mdt.until(now, ChronoUnit.MONTHS);
age += months + 'M ';
mdt = mdt.plusMonths(months);
long days = mdt.until(now, ChronoUnit.DAYS);
age += days + 'D ';
mdt = mdt.plusDays(days);
long hours = mdt.until(now, ChronoUnit.HOURS);
age += hours + 'h ';
mdt = mdt.plusHours(hours);
long minutes = mdt.until(now, ChronoUnit.MINUTES);
age += minutes + 'm ';
mdt = mdt.plusMinutes(minutes);
long seconds = mdt.until(now, ChronoUnit.SECONDS);
age += hours + 's';
return age; (6)
-
Parse the datetime "now" as input from the user-defined params.
-
Store the datetime the message was received as a
ZonedDateTime
. -
Find the difference in years between "now" and the datetime the message was received.
-
Add the difference in years later returned in the format
Y <years> …
for the age of a message. -
Add the years so only the remainder of the months, days, etc. remain as the difference between "now" and the datetime the message was received. Repeat this pattern until the desired granularity is reached (seconds in this example).
-
Return the age of the message in the format
Y <years> M <months> D <days> h <hours> m <minutes> s <seconds>
.
How painless dispatches functions
Painless uses receiver, name, and arity
for method dispatch. For example, s.foo(a, b)
is resolved by first getting
the class of s
and then looking up the method foo
with two parameters. This
is different from Groovy which uses the
runtime types of the
parameters and Java which uses the compile time types of the parameters.
The consequence of this that Painless doesn’t support overloaded methods like
Java, leading to some trouble when it allows classes from the Java
standard library. For example, in Java and Groovy, Matcher
has two methods:
group(int)
and group(String)
. Painless can’t allow both of these methods
because they have the same name and the same number of parameters. So instead it
has group(int)
and namedGroup(String)
.
We have a few justifications for this different way of dispatching methods:
-
It makes operating on
def
types simpler and, presumably, faster. Using receiver, name, and arity means that when Painless sees a call on adef
object it can dispatch the appropriate method without having to do expensive comparisons of the types of the parameters. The same is true for invocations withdef
typed parameters. -
It keeps things consistent. It would be genuinely weird for Painless to behave like Groovy if any
def
typed parameters were involved and Java otherwise. It’d be slow for it to behave like Groovy all the time. -
It keeps Painless maintainable. Adding the Java or Groovy like method dispatch feels like it’d add a ton of complexity which’d make maintenance and other improvements much more difficult.
Painless Debugging
Debug.Explain
Painless doesn’t have a
REPL
and while it’d be nice for it to have one day, it wouldn’t tell you the
whole story around debugging painless scripts embedded in OpenSearch because
the data that the scripts have access to or "context" is so important. For now
the best way to debug embedded scripts is by throwing exceptions at choice
places. While you can throw your own exceptions
(throw new Exception('whatever')
), Painless’s sandbox prevents you from
accessing useful information like the type of an object. So Painless has a
utility method, Debug.explain
which throws the exception for you. For
example, you can use _explain
to explore the
context available to a script query.
PUT /hockey/_doc/1?refresh
{"first":"johnny","last":"gaudreau","goals":[9,27,1],"assists":[17,46,0],"gp":[26,82,1]}
POST /hockey/_explain/1
{
"query": {
"script": {
"script": "Debug.explain(doc.goals)"
}
}
}
Which shows that the class of doc.first
is
org.opensearch.index.fielddata.ScriptDocValues.Longs
by responding with:
{
"error": {
"type": "script_exception",
"to_string": "[1, 9, 27]",
"painless_class": "org.opensearch.index.fielddata.ScriptDocValues.Longs",
"java_class": "org.opensearch.index.fielddata.ScriptDocValues$Longs",
...
},
"status": 400
}
You can use the same trick to see that _source
is a LinkedHashMap
in the _update
API:
POST /hockey/_update/1
{
"script": "Debug.explain(ctx._source)"
}
The response looks like:
{
"error" : {
"root_cause": ...,
"type": "illegal_argument_exception",
"reason": "failed to execute script",
"caused_by": {
"type": "script_exception",
"to_string": "{gp=[26, 82, 1], last=gaudreau, assists=[17, 46, 0], first=johnny, goals=[9, 27, 1]}",
"painless_class": "java.util.LinkedHashMap",
"java_class": "java.util.LinkedHashMap",
...
}
},
"status": 400
}
Once you have a class you can go to Painless API Reference to see a list of available methods.
Painless execute API
experimental::[The painless execute api is new and the request / response format may change in a breaking way in the future]
The Painless execute API allows an arbitrary script to be executed and a result to be returned.
| Name | Required | Default | Description |
|---|---|---|---|
|
yes |
- |
The script to execute. |
|
no |
|
The context the script should be executed in. |
|
no |
- |
Additional parameters to the context. |
Contexts
Contexts control how scripts are executed, what variables are available at runtime and what the return type is.
Painless test context
The painless_test
context executes scripts as is and does not add any special parameters.
The only variable that is available is params
, which can be used to access user defined values.
The result of the script is always converted to a string.
If no context is specified then this context is used by default.
Example
Request:
POST /_scripts/painless/_execute
{
"script": {
"source": "params.count / params.total",
"params": {
"count": 100.0,
"total": 1000.0
}
}
}
Response:
{
"result": "0.1"
}
Filter context
The filter
context executes scripts as if they were executed inside a script
query.
For testing purposes, a document must be provided so that it will be temporarily indexed in-memory and
is accessible from the script. More precisely, the _source, stored fields and doc values of such a
document are available to the script being tested.
The following parameters may be specified in context_setup
for a filter context:
- document
-
Contains the document that will be temporarily indexed in-memory and is accessible from the script.
- index
-
The name of an index containing a mapping that is compatible with the document being indexed.
Example
PUT /my-index-000001
{
"mappings": {
"properties": {
"field": {
"type": "keyword"
}
}
}
}
POST /_scripts/painless/_execute
{
"script": {
"source": "doc['field'].value.length() <= params.max_length",
"params": {
"max_length": 4
}
},
"context": "filter",
"context_setup": {
"index": "my-index-000001",
"document": {
"field": "four"
}
}
}
Response:
{
"result": true
}
Score context
The score
context executes scripts as if they were executed inside a script_score
function in
function_score
query.
The following parameters may be specified in context_setup
for a score context:
- document
-
Contains the document that will be temporarily indexed in-memory and is accessible from the script.
- index
-
The name of an index containing a mapping that is compatible with the document being indexed.
- query
-
If
_score
is used in the script then a query can specify that it will be used to compute a score.
Example
PUT /my-index-000001
{
"mappings": {
"properties": {
"field": {
"type": "keyword"
},
"rank": {
"type": "long"
}
}
}
}
POST /_scripts/painless/_execute
{
"script": {
"source": "doc['rank'].value / params.max_rank",
"params": {
"max_rank": 5.0
}
},
"context": "score",
"context_setup": {
"index": "my-index-000001",
"document": {
"rank": 4
}
}
}
Response:
{
"result": 0.8
}


=== Test case: lasp_SUITE:contracted_latency_test/1 (click for source code)
=== Config value:
[{watchdog,<0.450.0>},
<EMAIL_ADDRESS>{tc_group_properties,[]},
{tc_group_path,[]},
{data_dir,"/Users/anne-francevanswieten/lasp/_build/test/lib/lasp/test/lasp_SUITE_data/"},
<EMAIL_ADDRESS>=== Current directory is<EMAIL_ADDRESS>=== Started at 2017-04-18 14:13:43
*** User 2017-04-18 14:13:43.321 ***
Beginning case: contracted_latency_test
*** User 2017-04-18 14:13:43.336 ***
14:13:43.336 [info] Configured peer_service_manager partisan_default_peer_service_manager on node runner@MBPdeAnneFrance
*** User 2017-04-18 14:13:44.606 ***
14:13:44.605 [info] Enabling membership...
*** User 2017-04-18 14:13:44.607 ***
14:13:44.607 [info] Disabling blocking sync...
*** User 2017-04-18 14:13:44.611 ***
14:13:44.611 [info] Configured peer_service_manager partisan_default_peer_service_manager on node 'node-1@MBPdeAnneFrance'
*** User 2017-04-18 14:13:46.073 ***
14:13:46.073 [info] Enabling membership...
*** User 2017-04-18 14:13:46.074 ***
14:13:46.074 [info] Disabling blocking sync...
*** User 2017-04-18 14:13:46.078 ***
14:13:46.078 [info] Configured peer_service_manager partisan_default_peer_service_manager on node 'node-2@MBPdeAnneFrance'
*** User 2017-04-18 14:13:47.547 ***
14:13:47.547 [info] Enabling membership...
*** User 2017-04-18 14:13:47.549 ***
14:13:47.549 [info] Disabling blocking sync...
*** User 2017-04-18 14:13:47.553 ***
14:13:47.553 [info] Configured peer_service_manager partisan_default_peer_service_manager on node 'node-3@MBPdeAnneFrance'
*** User 2017-04-18 14:13:47.823 ***
Joining node: 'node-3@MBPdeAnneFrance' to runner@MBPdeAnneFrance at port 49254
*** User 2017-04-18 14:13:47.827 ***
Joining issued: 'node-3@MBPdeAnneFrance' to runner@MBPdeAnneFrance at port 49254
*** User 2017-04-18 14:13:47.827 ***
Joining node: 'node-2@MBPdeAnneFrance' to runner@MBPdeAnneFrance at port 49239
*** User 2017-04-18 14:13:47.828 ***
Joining issued: 'node-2@MBPdeAnneFrance' to runner@MBPdeAnneFrance at port 49239
*** User 2017-04-18 14:13:47.828 ***
Joining node: 'node-1@MBPdeAnneFrance' to runner@MBPdeAnneFrance at port 49226
*** User 2017-04-18 14:13:47.832 ***
Joining issued: 'node-1@MBPdeAnneFrance' to runner@MBPdeAnneFrance at port 49226
*** User 2017-04-18 14:13:47.892 ***
Waiting for join to complete with manager: partisan_default_peer_service_manager
*** User 2017-04-18 14:13:47.894 ***
Finished.
*** CT 2017-04-18 14:13:47.907 *** COVER INFO
Adding nodes to cover test: [runner@MBPdeAnneFrance]
*** CT 2017-04-18 14:13:47.914 *** COVER INFO
Successfully added nodes to cover test: []
*** User 2017-04-18 14:13:47.914 ***
Case finished: contracted_latency_test
*** User 2017-04-18 14:13:54.954 ***
14:13:54.954 [info] Application lasp exited with reason: stopped
=== Ended at 2017-04-18 14:13:54
=== successfully completed test case
=== Returned value: ok
Test run history
| Top level test index


AKAN NAMES
According to The Ghana Culture, They name their children according to the day they were born. The given name Corresponding to the day of the week they were born.
Lets Give It a try You Input your Birthday date on to the form and let's have a look Of Your Akan Name
Male
Sunday: Kwasi
Monday: Kwadwo
Tuesday: Kwabena
Wednesday: Kwaku
Thursday: Yaw
Friday: Kofi
Saturday: Kwame
Female
Sunday: Akosua
Monday: Adwoa
Tuesday: Abenaa
Wednesday: Akua
Thursday: Yaa
Friday: Afua
Saturday: Ama


name is too short.
lastname name is required.
Enter a valid email.
Allowed formats: jpeg, jpg, gif, png


Problem
We @Healθ believe that the information technology will play a large role in improving the quality of care, reducing costs and boosting efficiency. At the moment there are many issues which are plauging the healthcare industry, Some of them are, Lack of Meaningful Use, Inneficient Health Information Exchange, Poor Patient Engagement, Lack of Clinical Data Analysis.


void swf_actionwaitforframe ( int $framenumber , int $skipcount )
The swf_actionwaitforframe() function will check to see if the frame, specified by the framenumber parameter has been loaded, if not it will skip the number of actions specified by the skipcount parameter. This can be useful for "Loading..." type animations.
No value is returned.


2019 Volvo XC90 R-Design long-term review: Farewell
The Volvo XC90 is fast becoming a bit of an oldie in the large luxury SUV segment, but we think it's still a goodie.
by Sam PurcellRating: 8.4
$90,930 – $108,130 Dealer
- Fuel Economy
5.9L - Engine Power
173kW - CO2 Emissions
154g - ANCAP Rating
5Stars
Looking for a deal on this car?
Pros and Cons
Pros
- Uncluttered interior is spacious and comfortable, with room enough for seven
- Stacks of safety and advanced driving aids
- Rides well, despite the big 22-inch wheels
Cons
- Driveline can feel a little hurried at times
- Not as fuel-efficient as Volvo thinks
- shares
It's time to draw our last conclusions on the Volvo XC90 R-Design, which we've had on long-term assignment at CarAdvice. In particular, it's a 2019 Volvo XC90 D5 R-Design with a list price of $101,900.
During the time of our tenure, the price has increased up to $102,990 in the change to MY20 models. Some small details in optional specifications have changed, as well.
R-Design specification is a bit of a sporty nod within the XC90 range, in terms of design. The 2-litre diesel gets a slight bump in power and torque (173kW/480Nm to 177kW/500Nm), although we aren't sure if that's enough to call the R-Design warmed up.
Compared to the $94,990 Momentum specification, you get a bigger 12.3-inch infotainment display, 20-inch alloy wheels (22s are a no-cost option), leather steering wheel and gear shifter, nappa leather seats, and lots of R-Design details inside and out.
There is some additional safety gear in this specification, as well: blind-spot monitoring, rear cross-traffic alert, and rear autonomous emergency braking.
The engine in question here is a 2.0-litre, twin-turbocharged four-cylinder diesel that makes 177kW and 500Nm running through an eight-speed automatic gearbox to all four wheels. Official fuel use is listed at 5.9L/100km on the combined cycle, but we haven't been able to meet that number.
While we nudged into the sixes and mostly sevens on straight highway runs, you’re better off budgeting on around 9.0L/100km on your own combined cycle. It’s a small engine pushing a fairly large vehicle, after all.
On the plus side, that small motor combines well with the eight-speed gearbox for daily driving duties.
Power delivery is sometimes less than smooth as the gearbox picks a ratio to deliver the go-forward you are looking for. It's a rare occurrence, however. The D5 driveline gives the XC90 an all-important air of refinement, with enough poke for most situations.
If diesel isn't your jam, you can opt for a turbocharged and supercharged 2.0-litre petrol T6 R-Design motor, which is good for 246kW/440Nm. Or, spend big on the plug-in hybrid T8 that claims a combined total output of 300kW.
The interior is one that grows on you in the long term. There are plenty of quality touches and finishes around the place, and the general ambience of simplicity works in terms of practicality and aesthetic.
The infotainment display, measuring in at 12.3 inches' worth of portrait goodness, has been a good companion over the long term. It’s easy to get your bearings, despite having only one button.
Swiping and prodding are responsive, and feel natural. The important boxes of digital radio, Android Auto, Apple CarPlay and native navigation are all ticked.
One favourite element about this display is the crisp and detailed 360-degree camera system that it portrays.
The XC90 is certainly a big vehicle, but good visibility, light steering and this great camera system make it easy to navigate into and out of parks and other tight spots. Which is a good thing, because those 22-inch wheels are going to hit gutter well before any tyre does.
And if you don’t feel confident, there’s also a self-parking function for reverse parallel and perpendicular moves. Surely, it would be difficult to butcher a park in this car.
The display is also bolstered by a digital instrument binnacle, which has a variety of adjustable displays at the ready. It's functional and practical, along with adding that premium feel to the driving experience.
Ditto the knurled aluminium dials, and the tasteful combination of carbon-fibre look and piano-black materials.
Looking and feeling good is one thing, but the fact that seven adults can fit in with relative comfort gives a nod to the available space of the XC90's cabin.
We were pragmatic and stuck the smaller humans into the third row, which is not outright spacious but certainly good enough.
The least comfortable was probably old mate in the middle of the second row, but once again it's equal to other SUVs and passable for short trips.
Because there is air suspension and 500Nm low in the rev range (1500–2500rpm), the Volvo didn't particularly suffer from having somewhere between 550 and 600kg of human beings aboard. For a family SUV, this is an important point.
The Volvo plays to its traditional strength of safety well, with the full suite of active and passive safety technology accounted for.
Unlike other makes and models, we didn't experience any 'false positives' with the XC90, suggesting it's a well-tuned system. The semi-autonomous driving mode, Pilot Assist, is also impressive in its accuracy and ease of use.
The XC90 does a great job of hiding its age, in a segment where flashy new models are permanently just around the corner.
Considering it came out in 2014, the XC90 can still hold up its head as a refined and resolved luxury SUV that can stick a good fight to the more mainstream luxury player. It's still certainly worth consideration, especially now that capped-price servicing has come into play.
MORE: Long-term report one: Introduction
MORE: Long-term report two: Interior
MORE: Long-term report three: Infotainment
MORE: Long-term report four: Urban driving
MORE: Long-term report five: Highway driving
MORE: XC90 news, reviews, comparisons and videos
MORE: Everything Volvo
Our Ratings Breakdown
Rating: 8.4
7.7 Performance
8.5 Ride Quality
8.5 Handling & Dynamics
8.8 Driver Technology
8.5 Interior Comfort & Packaging
8.7 Infotainment & Connectivity
7.5 Fuel Efficiency
9.0 Safety
8.4 Value for Money
8.5 Fit for Purpose
Our ratings explained
Looking for a deal on this car?
1
56
nextprevious
2019 Volvo XC90 R-Design long-term review: Farewell


Donations
Here you can find donations from families, local stores and restaurants.
You can find food, clothes, toys and many other things.
Borrow/Exchange
Here you can borrow clothes that don't fit, tools that you don't need.
Vehicles, machineries and spare parts. Give life to unused items.
Food Sales and Offers
Here you can find sales from local groceries, restaurants & taverns.
High quality food that didn't get consumed through the day could be offered in very low prices.
Fruits and Vegetables which are not good looking but hold their nutritional value could be included.
Local Jobs
Here you can find seasonal job opportunities in agriculture and other local businesses.


Text Effect
Add attributes data-text-eff="letters-eff-{EFF}-{INDEX}"
and data-text-eff-speed="800"
to any HTML tag.
The value of {EFF}
are: fadeInRight, zoomInDown, flyInOut, fading, floatingUp, scaleIn.
The value of {INDEX}
can be any different character.


Shoes
Apparel
Training
About
If you love to run look no further!
Thanks to Kyle Cassidy for the publicly licensed
photo


Hello All,
First of all i would like you to know that i am a very beginner in programming and making different circuits using Arduino, Rasberry Pi and so on.
In the same time i would like to ask the Admin to move this post / topic or to delete it if is discussed somewhere else and to lead me through a link to it.
I have the following mats:
-SCT-013-000 - 1 piece
- Arduino -2 pieces (Mega and UNO)
-NRF24L01 radio modules -2 pieces
-Rasberry Pi model 2 - 1 piece
What I would like to do?
Using the above mats to monitor the energy consumption in my house and to export this to Openhab (which already is showing me the temp and humid) and to display the following:
1. the instant watts consumption
2. the Kwh consumption calculated from a certain date as for example starting from the beginning to the end of the current moth and to start counting from the beginning when the nest month begins
3. to display the total Kwh since the program was uploaded in the Arduino.
To accomplish this do i need to use only the SCT sensor or is necessary to use the AC-AC transformer too according to the diagrams shown on the site.
Any advice, link, suggestion, example will be kindly appreciated.
Thanks in advace,
DragosC
Re: Openhab nRF24L01+ energy monitor
I shall only answer this one question: "do I need to use only the SCT sensor or is necessary to use the AC-AC transformer too?". There are others here who can answer the other questions better than I can.
NO, you do not need to use a transformer to measure the voltage, but this is what happens:
The voltage at your house will vary according to how much power you and your neighbours are taking from the supply, and 'neighbours' may include your city or a large part of your country.
With a transformer, you know the voltage all of the time. Also, you know the phase relationship between the voltage and the current. Taken together, these things mean that you can calculate power, and therefore energy, to the best accuracy.
Without a transformer, you must guess the average voltage that you receive, and you must guess the power factor (see Building Blocks if I use a term you do not understand) and so the power you calculate will be less accurate. Over time, and by carefully adjusting the calibration, the inaccuracies might even out.
You do not say anything about your electricity supply or which country you are in, so I cannot guess what sort of supply you have. I do guess that you have only a single phase supply because you have only one current transformer. If you have a three-phase supply, you really must measure the current of each phase, that means 3 CTs, and ideally you measure the voltage of each phase also (but many people are happy to measure only the voltage of one phase because generally the three vary together).
Re: Openhab nRF24L01+ energy monitor
Thanks for the answer Robert.
As you already guessed i live in my apartment and i have a single phase power supply but this is not the point.
I asked if i may use only the CT without the transformer because transformer i bought even if it is labeled to convert 240V-9V Ac-Ac when i measure it with my tester it shows me 12V on the output so i was afraid not to burn the Arduino board using it! On the other hand if you use a transformer than you need to use another analog pin of Arduino and so less memory available.
I know very well that this topic is a very complex one because it suppose that you need to combine and to know two different things like: Programming the Arduino board, programming the rules in Openhab which is different than Arduino.
I want to use the serial gateway communication between the two Arduinos (those who worked already with Openhab know what is all about) so my ask would be that if can i find somewhere here or else an example for this kind of request: instant power consumption, kwh to date, total kwh.
The second part although I know this is not maybe the right forum to ask (Openhab) would be to find some Openhab rule example for this Arduino code thinking that in this huge community maybe there is one guy who did it.
Thanks All!
Re: Openhab nRF24L01+ energy monitor
No, you won't harm your Arduino. The input circuit in Building Blocks is designed for that 12 V output on no load, which is quite normal for a small 9 V transformer! The transformer is designed to give you 9 V at full load, and without a load the voltage will rise significantly, as you've found.
Hopefully, someone who knows Openhab will answer your other questions. I think you should be able to use emonHub on your Raspberry Pi. EmonHub is designed to accept radio (with an RFM69Pi module from our shop) or wired data from your emonTx/Arduino and send it via Ethernet to your router and then to emoncms.org. But I know that it can be used to send data to other places too. Hopefully Paul "pb66" will tell you about that.
Re: Openhab nRF24L01+ energy monitor
Thanks again for your reply, ill try to use this schemes found on this site to see what can i read on the Arduino serial monitor using this CT sensor.
The bad thing is that i don't know how to make the Arduino sketch to display these three values: instant watts, kwh to date and total kwh!
Please i need a little help here from those who tried this combination of Openhab, nrf24l01 Arduino and serial gateway communication!
Re: Openhab nRF24L01+ energy monitor
I haven't been around much and I missed this thread (sorry Robert) In theory it is possible to write a reporter for openHab and I would be keen to do so but I do not use openHab and therefore have zero experience of using it.
I would be happy to assist an experienced openHab'er bring openHab to emonHub but wouldn't try and tackle it alone. I recently looked into it and it appears each value would need sending individually (happy to be corrected there) when using the htttp/rest api and since openHan is on the cusp of v2 (as is emonHub) I felt it would be better to see how that panned out and try to implement a v2 to v2 solution at a later date.
If you or anyone wants to pursue this now though I will chip in where I can :-)
Paul
Re: Openhab nRF24L01+ energy monitor
Hi guys, I've managed to display instant power in Openhab, don't ask me how, long story.
I would like to ask you why when i test the current only sketch with every thing connected according to the diagram when i turn on the bulb which is labeled with 46W i get some values between 46 and 98 or near and when i turn of the bulb i get around 59-61!
All the mats are those explained on the site except that there no explanation how many volts the capacitor has to have but it is 10uf and so i bought some with 63 volts. The sensor is SCT-013-000.
How to calibrate the CT sensor to see on the serial monitor that when the bulb is off the displaied value is zero and when ON to see the right value?
UPDATE: i saw now if even the SCT is not connected to any wire it still display some values for the aparent power and Irms! It should show zero, isn't so?
Thank you!
Re: Openhab nRF24L01+ energy monitor
See the new FAQ page for the answers to your questions.
Re: Openhab nRF24L01+ energy monitor
I'm sorry, i read everything on get started and I know that all people ask different questions but I really don't understand how to calibrate this sensor.
If the diagram is ok and I test the current only eg, in my opinion it should display the right values! Right?
i really don't know what to change in the code! I tried to change different values according to my current 220v but nothing, I tried to make more spires on the sensor, still wrong values...
how is possible that without having anything connected to the sensor to get values like 15-25w ?
please help, this forum is to big to find the right answer soon.
thanks.
Re: Openhab nRF24L01+ energy monitor
Just a note about openHAB integration. I don't think we need to do anything special, since openHAB already has MQTT support. In my view MQTT is the perfect conduit for getting data from EmonCMS into openHAB and vice versa. I am currently doing this and it works very well. There is no need for either of the two systems to *know* about one another - they just have to publish/subscribe to the appropriate topics and that is it.
So my 2c would be, don't worry about any specific openHAB integration, but just focus on getting the MQTT side of things working so it is nice and easy for users to setup/configure/use. It also then becomes very easy to access that data in other systems, via MQTT as well (e.g. logging or monitoring systems).
I know there will be users who don't want the overhead of running their own broker and would like some sort of direct interface between the two systems, but as I say, that is just my 2c.
Re: Openhab nRF24L01+ energy monitor
I'm using OPENHAB with mqtt and I can get some data sensors from my arduino through nrf24l01 to my raspberry but I don't know any programming.
I have this sct sensor for more than 1 year and I wasn't able to make it work well!
hobestly I didn't understand how did u make the connection between OH and Emoncms! Do you have the both software installed on your pi or how? Where are you connecting the sensor? To any arduino or directly to your pi?
Your answer is a general one, more like an idea.
as I said here somewhere above, I have no programming knowledge, the only thing I can do is to work with them.
could you please come with more details? I need to know how to get the kWh in OH.
thanks.
Re: Openhab nRF24L01+ energy monitor
I have an Arduino Uno with an ethernet shield and the EmonTx shield on top. This is running a slightly modified sketch which takes sensor readings as normal, and then publishes them to my MQTT broker (on a different machine) over ethernet.
Once you get this working then it is a very simple task to setup an MQTT item binding in openHAB to subscribe to those topics and voila, you have your sensor data in openHAB.
In my case I don't actually send anything from EmonCMS to openHAB - I send the data to MQTT directly from my sensors (in my case the EmonTX Arduino). I then have another python script which monitors the same MQTT topics and forwards the sensor readings to EmonCMS via HTTP requests (using mqttwarn).
This is not the simplest system to explain, but it works very well since the sensor data is only published once by my EmonTX, but is consumed by both EmonCMS and openHAB.
There is work being done at the moment to add MQTT support to EmonCMS, which I haven't tried myself. But the idea should be that you get your sensor data into EmonCMS (which I presume you have working?) and then EmonCMS is responsible for publishing it out onto an MQTT topic. Slightly different to my approach, but no different in terms of how openHAB will receive the data - i.e. on an MQTT topic.
Edited: typo -> I HAVEN'T tried the MQTT support in EmonCMS.
Re: Openhab nRF24L01+ energy monitor
"how is possible that without having anything connected to the sensor to get values like 15-25w ?"
The analogue part of the ATMega 328P is picking up electrical noise from the digital part. It cannot tell the difference between that and the the signal you want from the CT.
Remember that the maximum you can measure is 100 A, which is equivalent to about 23 kW, therefore the 20 W you are seeing is only 0.1% of the maximum reading. You cannot expect accurate values below 200-300 W.
Re: Openhab nRF24L01+ energy monitor
@Robert Wall
Oh, so you say whatever I'll do I can't loose this noise?
At 23kw total, 0,1 noise is not so much but on my test with this 46w bulb to have 24w noise its a huge difference more like 50% error!
I saw a lot of movies on different sites where people tested the sct sensor with different apps and on their tests if the devices is unplugged the sct display 0 wh consumption and when plugged in whatever power the devices had, but they never show how they did the sensor calibration, only links to open energy (here) or nothing on the description.
@sumnerboy you use the Emontx and so you have a different approach on you installation. I want to use only the Arduino board directly to my Rasberry through this wireless nRF24L01 devices using the RF24 available libraries on git.
Re: Openhab nRF24L01+ energy monitor
There is probably very little that you can do about the noise. If you make sure that you have good grounding, good screening for your (sensitive) analogue front end, a good noise-free power supply, that is probably all that you can do. I understand that some Arduino boards have a filter in the 5 V power supply between the analogue and digital sections, but that most do not.
If your noise value is always the same number (or nearly), you could subtract that number in the sketch.
Alternatively, you can use a multi-turn primary winding with your CT - you loop the wire through many times, and that multiplies the current that you read but not the noise (then of course you divide the answer in the sketch to give the correct result).
Re: Openhab nRF24L01+ energy monitor
I am testing this on two different boards, Arduino Uno and Arduino Mega, both original bought from the official supplier.
Tell me please how can I substract this difference in the current only example? It should be something like minus the difference that the CT is showing without being connected to any alive wire?
I tried also multi-turn but still this huge noise and to do this in a panel where all cables are FYY = 8 or 10 it's kinda of impossible.
Re: Openhab nRF24L01+ energy monitor
How are you powering the Arduinos? A ripply 5V supply is a common cause for ADC noice. Check out this thread too: http://openenergymonitor.org/emon/node/10111


My goals for the weeks were:
I completed the Eloquent JavaScript exercises and created a basic website for my hat project. There are elements of the site that I would like to develop further including incorporating a hamburger menu for smaller screens and fixing a couple of layout issues.
I did not complete my second goal - setting aside time to work on JavaScript challenges in FreeCodeCamp. Instead, I decided to focus on learning elements of JavaScript that would be more relevant to my personal project of trying to create an app where the user can design their own hat. I spent time learning about canvas and how to create brush and colour fill elements using JavaScript. This is something I really enjoyed and I hope to continue to spend more time on over the coming week.
My stretch goal was to plan how I would build the 'design your own hat' feature. While I don’t have a pseudocoded plan all ready to implement, I did research and have some ideas about how this could be achieved using canvas. This has given me a clear starting point to develop on from over the next couple of weeks.
This week I learned about canvas and how to create a drawing app using html and JavaScript. I found lots of online resources that were really helpful in introducing canvas and how it can be used. I am still finding JavaScript confusing and rely heavily on notes and online info so am super happy when sometimes things work.
This week I enjoyed creating a drawing app using canvas. Although it is fairly basic and I very closely followed a video tutorial, I am pretty excited about the possibilities and am hoping that as I explore this further I'll be able to develop my understanding of JavaScript too.


Updated bank details sucessfully
Could not updated bank details
Deleted Bank sucessfully
Could not delete bank. bank does not exist
Enter Bank ID
Bank ID
×
Bank ID
Bank Name


yield climate maize precipitation maximum ENSO effects southeastern temperature temperatures years June Niño U.S. weather {border-style crop increase monthly px;} yields #ffffff;} greater month-specific trends Niña change growth kg ha conditions effect locations observed Climate Supplementary Table associated cumulative data differences increased season soil strong However, Material growing production reproductive anomalies patterns stages July agricultural analysis average impacts importance influence months phase px; result trend {font-family Oscillation Res. characterized compared font-size moisture negative period potential significant suppression variability vegetative water Belle Therefore, annual both, double; higher included phases results spring studies surface years. April Maize Meteorol. Prattville border-color border-width climatic early events in-season locations. lower phase. solid; study used year-to-year yield, {font-style {font-weight °C (e.g., . °C Additionally, Agric. Agron. Appl. Change Climatol. Field Huang Lobell Mina Neutral Niño-Southern North Southern Tifton USA Yield agreement attributed average, averaged based bold change. combined content contributed courier; database em; examined final first-year impact late non-irrigated planting precipitation, previous pt;} respectively. resulted soybean strongly values variability. vary wheat yield. mm −yr


| 1 | package nl.tudelft.jpacman.npc.ghost; | |
| 2 | ||
| 3 | import java.util.List; | |
| 4 | import java.util.Map; | |
| 5 | ||
| 6 | import nl.tudelft.jpacman.board.Direction; | |
| 7 | import nl.tudelft.jpacman.board.Square; | |
| 8 | import nl.tudelft.jpacman.level.Player; | |
| 9 | import nl.tudelft.jpacman.sprite.Sprite; | |
| 10 | ||
| 11 | /** | |
| 12 | * <p> | |
| 13 | * An implementation of the classic Pac-Man ghost Shadow. | |
| 14 | * </p> | |
| 15 | * <p> | |
| 16 | * Nickname: Blinky. As his name implies, Shadow is usually a constant shadow on | |
| 17 | * Pac-Man's tail. When he's not patrolling the top-right corner of the maze, | |
| 18 | * Shadow tries to find the quickest route to Pac-Man's position. Despite the | |
| 19 | * fact that Pinky's real name is Speedy, Shadow is actually the fastest of the | |
| 20 | * ghosts because of when there are only a few pellets left, Blinky drastically | |
| 21 | * speeds up, which can make him quite deadly. In the original Japanese version, | |
| 22 | * his name is Oikake/Akabei. | |
| 23 | * </p> | |
| 24 | * <p> | |
| 25 | * <b>AI:</b> When the ghosts are not patrolling in their home corners (Blinky: | |
| 26 | * top-right, Pinky: top-left, Inky: bottom-right, Clyde: bottom-left), Blinky | |
| 27 | * will attempt to shorten the distance between Pac-Man and himself. If he has | |
| 28 | * to choose between shortening the horizontal or vertical distance, he will | |
| 29 | * choose to shorten whichever is greatest. For example, if Pac-Man is four grid | |
| 30 | * spaces to the left, and seven grid spaces above Blinky, he'll try to move up | |
| 31 | * towards Pac-Man before he moves to the left. | |
| 32 | * </p> | |
| 33 | * <p> | |
| 34 | * Source: http://strategywiki.org/wiki/Pac-Man/Getting_Started | |
| 35 | * </p> | |
| 36 | * | |
| 37 | * @author Jeroen Roosen | |
| 38 | * | |
| 39 | */ | |
| 40 | public class Blinky extends Ghost { | |
| 41 | ||
| 42 | /** | |
| 43 | * The variation in intervals, this makes the ghosts look more dynamic and | |
| 44 | * less predictable. | |
| 45 | */ | |
| 46 | private static final int INTERVAL_VARIATION = 50; | |
| 47 | ||
| 48 | /** | |
| 49 | * The base movement interval. | |
| 50 | */ | |
| 51 | private static final int MOVE_INTERVAL = 250; | |
| 52 | ||
| 53 | /** | |
| 54 | * Creates a new "Blinky", a.k.a. "Shadow". | |
| 55 | * | |
| 56 | * @param spriteMap | |
| 57 | * The sprites for this ghost. | |
| 58 | */ | |
| 59 | // TODO Blinky should speed up when there are a few pellets left, but he | |
| 60 | // has no way to find out how many there are. | |
| 61 | public Blinky(Map<Direction, Sprite> spriteMap) { | |
| 62 | super(spriteMap, MOVE_INTERVAL, INTERVAL_VARIATION); | |
| 63 | } | |
| 64 | ||
| 65 | /** | |
| 66 | * {@inheritDoc} | |
| 67 | * | |
| 68 | * <p> | |
| 69 | * When the ghosts are not patrolling in their home corners (Blinky: | |
| 70 | * top-right, Pinky: top-left, Inky: bottom-right, Clyde: bottom-left), | |
| 71 | * Blinky will attempt to shorten the distance between Pac-Man and himself. | |
| 72 | * If he has to choose between shortening the horizontal or vertical | |
| 73 | * distance, he will choose to shorten whichever is greatest. For example, | |
| 74 | * if Pac-Man is four grid spaces to the left, and seven grid spaces above | |
| 75 | * Blinky, he'll try to move up towards Pac-Man before he moves to the left. | |
| 76 | * </p> | |
| 77 | */ | |
| 78 | @Override | |
| 79 | public Direction nextMove() { | |
| 80 | // TODO Blinky should patrol his corner every once in a while | |
| 81 | // TODO Implement his actual behaviour instead of simply chasing. | |
| 82 | Square target = Navigation.findNearest(Player.class, getSquare()) | |
| 83 | .getSquare(); | |
| 84 | ||
| 85 |
1
1. nextMove : negated conditional → SURVIVED |
if (target == null) { |
| 86 |
1
1. nextMove : mutated return of Object value for nl/tudelft/jpacman/npc/ghost/Blinky::nextMove to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return randomMove(); |
| 87 | } | |
| 88 | | |
| 89 | List<Direction> path = Navigation.shortestPath(getSquare(), target, | |
| 90 | this); | |
| 91 |
2
1. nextMove : negated conditional → SURVIVED 2. nextMove : negated conditional → SURVIVED |
if (path != null && !path.isEmpty()) { |
| 92 |
1
1. nextMove : mutated return of Object value for nl/tudelft/jpacman/npc/ghost/Blinky::nextMove to ( if (x != null) null else throw new RuntimeException ) → SURVIVED |
return path.get(0); |
| 93 | } | |
| 94 |
1
1. nextMove : mutated return of Object value for nl/tudelft/jpacman/npc/ghost/Blinky::nextMove to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return randomMove(); |
| 95 | } | |
| 96 | } | |
Mutations | ||
| 85 |
1.1 |
|
| 86 |
1.1 |
|
| 91 |
1.1 2.2 |
|
| 92 |
1.1 |
|
| 94 |
1.1 |


‘MESSI! MESSI! MESSI!’: What We Learned From FC Barcelona’s 4-1 Victory Over Celta Vigo
by Tom SandersonThanks to Lionel Messi’s mastery and set piece hat trick, FC Barcelona headed back to the top of La Liga with a 4-1 win over Celta Vigo at the Camp Nou on Saturday. Here’s what we learned during the tie. Valverde had a few surprises up his sleeve
Samuel Umtiti started at centre-back instead of compatriot Clement Lenglet, Sergi Roberto got the nod in central midfield as opposed to Sergio Busquets and though Luis Suarez being on the bench was no shock, Antoine Griezmann was finally awarded the central role meant for him when the Uruguayan picked up an injury against Levante last weekend.
Roberto began well
Often in Busquet’s pivot role, he had early success akin to Arturo Vidal when charging forward at times, and his chaos resulted in the ball dropping to Messi’s feet for Barcelona’s first shot on goal around the quarter of an hour mark.
As did Ansu Fati
The 17-year-old looked far sharper than his last start at the Camp Nou, the 5-1 mauling of Valladolid, and his low cross into the box forced a handball for the penalty Messi converted to make it 1-0. Still, it wasn’t enough to not be brought off for Ousmane Dembélé during the break.
There was confusion over Nelson Semedo's exit
During the wait for the spot kick, the Portuguese right-back, who had been exchanging neat passes with Frenkie de Jong, was brought off for Sergi Busquets. With this, Roberto filled in at his and Semedo’s shared position, but rather than confirm the knock, some TV stations suggested the move was tactical.
It wasn’t however
According to Brazilian correspondent Marcelo Bechler, who is based in Barcelona, Semedo asked to come off and went straight into the changing room upon substitution. Prior to the second half getting underway, a calf issue was confirmed.
Junior Firpo again showed signs of naivety and inferiority
Caught out when pushing up to midfield on more than one occasion, Arthur of all people could be found covering for him at left back. Hopefully Alba can recover quickly and his right-back stand in Semedo’s niggle isn’t too serious, or Barcelona could have a real problem on their hands if the Domincan is their only option on the left of the back line. Admittedly, he was better at holding his line once his side were comfortably ahead.
Arthur was denied his fifth assist of the season
By the pitch not being big enough. Darting towards the edge of the box, he squared it to Messi in the six-yarder but the ball was shown to be out of play by some distance. Still it will have given the Brazilian a lift after a strange week or so being dropped twice from the last three squad lists.
Messi’s foul on the edge of the box allowed Celta to equalise
For once, albeit temporarily, it was not him wowing with a deadball pearler at the Camp Nou when Lucas Olaza ripped one past a fooled Marc-Andre Ter Stegen. The leveller looked like sending Barcelona down the tunnel at half time tied for the second consecutive match and needing a big second 45.
But this is Messi’s house
Not to be outdone, the five-time Ballon d’Or winner got the chance to put Barça 2-1 ahead when Arthur had his shirt pulled in perfect range. He made no mistake in converting the 51st free-kick of his career, and the Blaugrana went off to chants of ‘MESSI! MESSI! MESSI!’ in adoration as opposed to the jeering whistles.
Messi: Three of Barcelona’s last three and not even playing that well
At least not by his standards. The Slavia game midweek was scoreless, yet he hit a penalty in at Levante and another one here tonight before the free-kick. This represented all three of his side’s three goals in their last three games up to this point, while simultaneously demonstrating that Messi-dependance has never been stronger. Upon sealing his third, the stat could be updated to all four of FCB’s last four strikes over the line.
The Messi-Griezmann connection continued to falter
Messi could be seen trying to play his teammate in on one move, but there was not a single completed pass between the pair in the first half.
Dembélé made an instant impact
Replacing Fati on the right while Griezmann moved to the left, he ran into the box with his ambidextrous trickery and was unlucky not to curl his shot into the top corner from the corner of the 18-yard-box. Later, with 20 minutes to spare, he played a brilliant low driven pass that Messi slid in for and almost got a foot to.
Celta were gluttons for punishment in allowing Messi a second chance from dangerous quarters
Messi completed his hat-trick in the 48th minute with another free-kick that was almost a carbon copy of the three others scored in the Camp Nou this season. It really is getting quite ridiculous now...
Messi and Griezmann worked better once Messi completed his hat trick
And Messi looked genuinely disappointed, in that he wanted Grizi to score, when the World Cup winner could not convert around an hour in after releasing him. At long last, there were other exchanges between them that preceded the effort.
Griezmann is winning over the fans
Brought off for Suarez in the 73rd, he was cheered by the Camp Nou faithful for his contribution despite not being that impressive. Owing to the change, Dembélé switched to the left.
Busquets showed off his finishing nous for the fourth
His starting absence for all three of Barcelona’s defeats in 2019/2020 well-documented, Busquets wonderfully drilled home a bouncing shot five minutes from time when a headed clearance from Dembélé’s dipping ball sat up nice for him.
Barcelona are back on top
Heading into the international break, they top La Liga through their +2 superior goal difference over Real Madrid. Both sides currently on 25 points, we are set for a scintillating Clasico a week before Christmas if they can keep up this up.