text:
God's Big World
WorldKids
WorldTeen
The gospel according to Pete
Democratic presidential candidate Pete Buttigieg speaks often of his religion—but he tailors it to fit his politics, and it focuses on works over faith
Groundhog years in Argentina
Argentina was once one of the richest countries in the world, but an embrace of ever-growing government made it poor
Invisible hands
Anyone can be an author nowadays, but knowing who wrote the book may be a different story
An evil traffic
In the Netherlands, legal prostitution hasn't turned out the way advocates predicted, and some are fighting to end it
Andrée Seu Peterson / Janie B. Cheaney / Joel Belz / Marvin Olasky / Mindy Belz / The Editors /
Sports / Lifestyle / Religion / History / Immigration / Medicine / Health / Law / Politics / Technology / Science / Business
Metro Minute / Snapshots of China / Sophia's World / Whirled Views /
Music / Q&A / Children's Books / Books / Movies / Television
Quick Takes / Quotables / Human Race / News
Voices Mindy Belz
Moral incoherence
A(nother) crisis unfolds in Syria while the U.S. focuses on oil
Post Date: November 07, 2019 - Issue Date: November 23, 2019
Displaced people from Tel Tamer in Syria gather in Hasakah for help. (Partners Relief & Development)
American Steve Gumaer had only been in Syria for hours when he learned 138 more families had arrived with no place to stay. The residents from the town of Tel Tamer fled Turkish bombardments, piling into open-bed trucks for a 40-mile trip that could mean the difference between life and death.
Gumaer, president of Partners Relief & Development, leads one of a handful of NGOs on hand to receive the displaced amid a sudden humanitarian crisis. An estimated 300,000 Syrians have been forced from their homes by the Turkish invasion of northeast Syria that began shortly after President Donald Trump announced a U.S. withdrawal Oct. 6.
Many of those fleeing have nowhere to go. The UN rejected one proposal to set up a temporary camp in Hasakah, where Gumaer's operations are based. Options along with resources are scarce in a country at war for eight years.
Gumaer and his team found the families in a park, the women sleeping in a long, hastily made tent with their children. The men gathered further away. "We gave them blankets and pads to sleep on," said Gumaer. "It's a huge challenge to know what else to do."
None of the key players have a plan for protecting civilians—leaving that to volunteers from Kurdish groups, local churches, and NGOs.
Large grain elevators on the way into Hasakah signal it once was the breadbasket of Syria. Now it's taking the brunt of forced displacement from Turkey's monthlong campaign to create a "safe zone" inside Syria. At least 180,000 Syrians have fled there, doubling the city's size.
At a meeting with Gumaer and other aid and church leaders, local officials agreed to close Hasakah's 68 schools to convert them into shelters. Partners already was running emergency kitchens out of 65 of the schools, so Gumaer leveraged contacts with teachers and administrators to convert classrooms into bedrooms and living spaces.
"We have 270 volunteers," Gumaer told me, nearly all of them locals whose lives also have been upended by weeks of Turkish incursions. Yet they went to work, clearing space and rearranging furniture.
Partners has worked in Iraq and among the Rohingya in Myanmar, but this crisis is unlike other, much larger ones, because the workers are so few. International aid agencies and government agencies normally on the scene are staying away from a chaotic, dangerous landscape.
Turkish forces have deployed drones to attack civilian areas, despite a cease-fire agreement, plus they have attacked outside their agreed-to buffer zone, where the Kurdish-led Syrian Democratic Forces (SDF) still have control.
President Donald Trump initially ordered the withdrawal of 100 U.S. soldiers embedded with the SDF at border positions, then a few days later ordered withdrawal of the entire U.S. contingent (about 1,000 troops), and in late October reversed that decision, sending U.S. troops back to secure oil fields.
As Turkish forces arrive, Syrian forces are moving north to take positions opposite them, Kurdish forces remain, and U.S. convoys can be seen moving in every direction. Yet none of the key players have a plan for protecting civilians—leaving that to volunteers from Kurdish groups, local churches, and NGOs like Gumaer's.
One came under deadly fire Nov. 3, when a Turkish mortar killed Free Burma Rangers medic Zau Seng. Seng was part of a team that for weeks had rescued civilians and wounded. He was working at a casualty collection point when it came under fire.
"Zau came in love and he left in love," said Dave Eubank, the group's director, but Eubank blamed Turkey for creating "not a safe zone, but a zone of invasion, a zone of death."
Leaders in the Syrian Democratic Council that has controlled northeast Syria since 2015 say the United States can monitor and stop Turkish strikes. "We hold the Pentagon responsible for all the crimes committed by Turkey if they don't close the airspace," said co-chair Ilham Ahmed. "It doesn't require any military commitment."
Alberto Fernandez, a former U.S. diplomat in the region who heads the U.S.-supported Middle East Broadcasting Networks, said in a Facebook post: "Turkish controlled Islamist fighters in Syria shell American Evangelical Christian humanitarian group, killing one (Burmese Christian) aid worker and wounding another. Meanwhile this President talks about 'protecting the oil' in Syria after abandoning religious and ethnic minorities to these thugs. Shameful moral incoherence at work."
More from Mindy Belz
Living with brutal realities
As the United States and Iran traded airstrikes in Iraq this month, Behnam Benoka made middle-of-the...
Refresh those bones
In our business a proverb about good news rarely gets the attention it deserves, but a journalist at...
Read more from Mindy Belz
More in Voices
Joel Belz
My turn: the three hardest words to say
"I WAS WRONG." Some wise soul says those are the three hardest words for a human being to say. ...
Janie B. Cheaney
Atheism's second thoughts
In a satirical epilogue to The Screwtape Letters, C.S. Lewis imagines his venerable old demon rising to propose a toast after the annual Tempters' Training College dinner. While commending his hosts, ...
You must be a WORLD Member and be logged in to the website to comment.
Posted: Sat, 11/09/2019 02:22 am
Maybe they should set up refugee camps in the oil fields. It sounds like the safest place.
Is the snark in the headline necessary? Mrs. Belz has made her contempt for President Trump plain. I don't read World for anti-Trump screeds. How to develop and implement American foreign policy is a difficult and thorny issue. It does not lend itself to the biblical simplicity of 'Thou shall not..." Mrs. Belz writes in such a way that it seems to violate World's journalistic scale. Strong, clear writing for level one issues where the bible is clear. Winsome writing is required for those issues where it doesn't speak as clearly. American foreign policy is one of the latter.


Share the post "Those Whom God Chooses…"
Alison was witness to incidents which indicated how Eugene was "going crazy" and trying to "break the bonds" without really knowing how to do so. She recalls the night when Eugene and John's argument about God came to a head. John, Eugene, Alison, and a few others had gone to the top of Mount Baldy, another local meeting place of the group of friends.
Everyone became drunk with wine, except Alison.
Then something unexpected happened. Eugene stood up and began shouting at John.
Let the same passion that filled Eugene's heart, fill our hearts too.


text:
Sri Lanka High Commission
Holidays Observed by the High Commission 2019
Sri Lanka – Kenya Bilateral Relations
Sri Lanka-Kenya Trade Relations
Concurrent Accreditation
High Commission Press Releases
Foreign Ministry Press Releases
Registration of Marriage
Registration of Death
Authentication of Documents
Payment of Pension
Importation of Animals
Sri Lanka Elected by Acclamation to the Executive Board at First UN Habitat Assembly
June 3, 2019 HE Press Releases
Sri Lanka was nominated by acclamation to the Executive Board at the First UN-Habitat Assembly held from 27-31st May 2019 in Nairobi, Kenya.
Kenyan President Uhuru Kenyatta ceremoniously inaugurated the First UN-Habitat Assembly (UNHA 1) under the theme "Innovation for a Better Quality of Life in Cities and Communities", with the participation of 113 countries including 44 Ministers, 60 Mayors were among the 2,250 delegates from all over the world. At the High-Level Segment, Salva Kiir, President of South Sudan, Frank Bainimarama, Prime Minister of Fiji, and Maeen Abdulmalik Saeed, Prime Minister of Yemen also participated.
Bernard Vasantha, Secretary Housing, Construction and Cultural Affairs leading the Sri Lanka delegation in his National Statement informed that Sri Lanka has aligned its housing programmes to achieve the Sustainable Development Goals (SDGs) in line with the New Urban Agenda and the good governance policies of Sri Lanka.
Highlighting some of the achievements, Secretary Bernard Vasantha stated that the core of the Western Regional Megapolis Planning Concept in Sri Lanka is to provide more green space for housing settlements. He added that his Ministry is in the process of amending existing Laws, Acts and Legislation as necessary, to facilitate the implementation of new SDGs. He added that Sri Lanka recently introduced the National Construction Policy to promote environment-friendly buildings with green building guidelines.
The other members of the delegation comprised of Sri Lanka High Commissioner to Nairobi, Sunil de Silva, L S Palansuriya, Chairman National Housing Development Authority, Christopher A. Wijeyeweere, Chairman, Condominium management Authority and Anzul Jhan, Deputy High Commissioner.
© 2021 Sri Lanka High Commission Nairobi. All Rights Reserved.Dellco Technologies Ltd

redpajama_set_name: RedPajamaCommonCrawl


There cannot be vehicles without brakes and that means they are a crucial component. If the brake parts are not working well, you cannot have a complete vehicle. You need to take the vehicle for brake repair regularly. Every day, before you drive away, you need to confirm the state of your brakes so that you do not end up with a brake failure while you are on the road. One way of knowing that the brakes are not working properly is noticing strange noise on stepping on the brake pedal. In such a case, you should take the vehicle to a professional to be inspected. If you are considerate about how safe you are on the road, you need to have your brakes repaired whenever they have a problem. An accident will most definitely be the end if the brakes fail while you are driving. Not all accidents are minor and if you end up in a fatal one because you were too lazy to have the vehicle brakes repaired will cause regrets. You also need to repair your brakes for the sake of other road users because the roads are for the entire public. Not fixing your brakes might mean death for someone else. The indecision might cost you highly because injuries to other people due to your mistakes will be on you.
Repairing your brakes on time will not be costly as will be the case if you wait for long. There will be servicing and insurance charges to be met and the last thing you need is to drive up the cost of maintaining the vehicle. In matters to do with savings, you do not have to wait until you have a lot of money to start saving which is why you should start by cutting back on some expenses like the cost of brake repair and save the extra. This is possible by making sure you do not wait until it is too late to fix your brakes. You won't need to change your brakes often if the repair work is done on time. You need to work on making sure you are not replacing the brakes when it can be prevented by timely repairs. Make sure the person you take the vehicle to is a professional at the job to avoid having to bring back the vehicle with a similar problem in the near future.
The best mechanics do not just fix the brakes and send you on your way but rather check whether there are other issues to be addressed by conducting a full inspection. People who love what they do and are skilled in brake repair will offer the best services and it is such you should be after. Once you identify a great mechanic, you will always rely on him or her.


text:
Home>New articles>Nevyanskaya inclined tower - there is a leaning tower in Russia!
Nevyanskaya inclined tower - there is a leaning tower in Russia!
by Addison
Have you been to Pisa? And I was not. But you know about the leaning tower of Pisa, and I know. Everyone knows about her. But there are a lot of falling and downhill towers in the world. Yes, and we in Russia have such, and not one, as it turned out.
Once I accidentally drifted into Nevyansk. This is a city in the Sverdlovsk region. Not quite by chance, of course - I went to visit my relatives. So they told me about this monument of falling architecture.
Nevyansk Inclined Tower
It stands there swinging, in the sense of falling, alreadylong ago, already from the 18th century. Built by order of Akinfiy Demidov, whose office was located on one of the floors. In fact, the Nevyansk leaning tower is not considered to be a falling one, since its slope remains unchanged. Its correct name is the Nevyansk Inclined Tower. For me, it makes no difference what you call it, so long as people know that there is such a thing in Russia, and why not go to Pisa. For the average person it doesn't matter at all whether its inclination changes or not, the main thing is to see. True, after all, an unusual sight.
Nevyanskaya inclined tower.
As we were told, the sloping tower was unknownoriginally built or later bent. And also it is not known why it was built at all. Here it is, the story! He knows everything, but he knows nothing. According to some reports, in this inclined Nevyansk tower coins were made of gold, the samples above the state. There are also stories about some flooded basements where these coins were kept and which no one can find now.
Nevyanskaya leaning tower.
Provincial landscape next to the falling tower
Nevyanskaya tower is permeated with a metal frame. Tightening beams can be seen inside the tower. Outside they are braced. The thickness of the walls of the lower floor is about two meters. And inside the wall there is a ladder. Feeling uncomfortable inside such a stratum.
Nevyanskaya leaning tower. Iron beams inside.
There is another interesting falling tower -auditory room with a cunning vaulted ceiling. Two people who are in the opposite corners of this room, and turned to face the wall, can talk to each other in a whisper, while no one will hear them in the center of the room and other corners. At first I did not believe it, but it really is. It seems that the other person is whispering right in your ear, although it is 5 meters away.
Auditory of the leaning tower.
On the top floor there are clocks, by typechimes. Just do not break. Brought from England, and cost a lot of dough, about as much as the inclined tower itself. Although if Demidov had his gold coins, then that he had this pile.
View of Nevyansk from the sloping tower.
I hope that the tower in Nevyansk will someday become as famous as the Leaning Tower of Pisa, and Nevyansk is a tourist city with European coziness.
New Year in Thailand - preparing for ...
Detailed maps of Abkhazia and cities of resorts
What to see in Anapa and where to go - on your own or with a guided tour
Phuket Apartment Overview
What to see in Hua Hin - attractions and excursions
Activities in Indonesia in August: prices and weather. Where to rest in Indonesia in August
Articles on Indonesia
How to cancel reservation on Booking com
Airport Nizhnevartovsk: diagram photo. How to get to Nizhnevartovsk airport


Our clients, a large Group of Accident Repair Centres are opening a brand new site in Keighley and are currently looking for an ATA Paint Sprayer.
A salary of between £25K to £45K plus benefits is offered for this role.
Seek clarification from the Bodyshop Manager or Bodyshop Administrator if a work order is not clear or seems incorrect.
Report accurately and correctly all components, materials, consumables and hours used on each vehicle repair, keeping wastage of all materials and consumables to the minimum.


text:
November 14, 2020 Team Politudes
The US Election is a Cautionary Tale for Progressive Government
… by Terrance Hunsley
The Democratic Party spent about $1B on advertising for Joe Biden. Stars endorsed him. An unpopular and widely demonized President botched-up the response to the pandemic, with people dying or losing their jobs. The Democrats had increasing education levels in the population and increasing urbanization on their side. Biden got support from a powerful group of Republicans. There were record turnouts for the vote. And yet, Biden received barely over half of the votes, squeaking out a narrow victory.
What some thought would be a tsunami of support for a progressive party was offset to some degree by people becoming more conservative as they age. But more importantly, there is in the US, across most of the political spectrum, a deep-seated mistrust of politicians, public institutions and collective policies. The election was combat, not competition, and political discourse reached an abysmal low. It would be hard to say that the Democrats have the confidence of the American people.
As WIlliam Galston wrote for the Brookings Brief;
For their part, Democrats must recognize that they defeated Trump but not Trumpism. The new coalition that the outgoing president forged will be a prominent feature of the political landscape for years to come, and there is little evidence that the forces that energized its formation have weakened. If Democrats are counting on demographic change to expand their modest popular edge into a truly national majority, they will likely have a long wait.
(https://www.brookings.edu/blog/fixgov/2020/11/12/in-the-popular-vote-why-wasnt-bidens-victory-bigger/utm_campaign=Brookings%20Brief&utm_medium=email&utm_content=99761329&utm_source=hs_email)
Of course, Canada is not the US. Our attitudes and our internal differences are more muted. But they are not contrasting. We are also experiencing a hardening of political attitudes. Our elections are increasingly characterized by attack ads, and we witness the spread of hate and social paranoia on social media. Too many Canadians consider government to be inept and corrupt. Respectful discussion of governance and goals for public policy are hard to find outside policy wonk circles. Parliament is a place more for political manoeuvring than policy debate. How often do we hear candidates tell us "I will fight for you!"? Who is fighting against us and why? And how often do we hear from friends, in discussion of our leaders, "I don't like them" rather than "I don't like their policies."
The pandemic has helped us to see the mutual dependence of government and the economy, and to appreciate the hard work by competent public servants and front line workers. But mistrust and non-confidence are still strong, and as we see in the US, the rejection of government can be virulent.
However, most people do seem to still value democracy, even if they think it's not working for them. So perhaps society's challenge is a better connection between democracy and accountable government. There could be better communication of the role and value of public goods and sharing risk. And perhaps we could articulate and value the reciprocal contract of citizenship.
National Goals
How to get there isn't totally clear, but we might start with better information on the goals of government, and how we are doing in getting there. That might mean formulating national goals for each main area of policy, and systematically reporting on progress. These goals need to be something that all parties can support, like increasing the health and education levels of the population, increasing employment levels, improving child health, decreasing opioid-induced deaths, decreasing homelessness, decreasing poverty. The development of these goals and their enactment in legislation, would be a unifying act in itself. Every government could be required to report regularly on them, snd political candidates could explain how their policy ideas would advance those goals.
Currently, government policies are sold to us as cure-alls, and we are told only the price tag – how many billions of dollars will be spent. But really, most of us have no way of knowing whether any figure – be it $20Billion or $80Million spent over five years – is the right amount, what its measurable goals are. and what other options could be considered. We hear opposing parties saying it will cost too much and lead to disaster, rather than present a better version.
We should receive regular, objective information on the progress and results of all government programs. How many people are lifted out of poverty? How many unemployed people found good jobs? How many people have a general practitioner to see about their health? How are we doing with cancer treatment? How many people graduate college or university each year, and at what public cost? How many jobs are supported by public money, and how many companies sell goods or services to governments? How many people are receiving CPP payments? What are the results of legalization of marijuana for crime and prisons? Each week could be a report on a major national goal.
Problem areas or performance shortfalls should be reported as well, emphasizing accountability over self-congratulation. This could be a responsibility of the Auditor General, reporting directly to Parliament and the public.
The goals would remain in place and be central to the discussion of progress in the country and its provinces, reevaluated at every election. It would be a bit like fact-checking in advance. It would help citizens understand the effectiveness of the government and for whom they might wish to vote.
Making citizenship important and reciprocal
During times of war and crises, including the pandemic, people feel more affinity for others. "We're in this together" appears on signs. For the most part, there is support for the authority and actions of government during these times. But, aside perhaps from the courses that immigrants are provided, people do not seem to be aware of the extent that citizenship makes them interdependent with government and each other.
We could provide better information on the underlying rationale of public policy. I have mentioned the CPP for example. Not everyone knows that the returns they receive from their contributions – not even counting the disability insurance they receive – their returns are better and more secure than they would receive if they had invested the same amount into the average mutual fund portfolio that banks peddle.
They might not realize that as children, their school costs are being paid for by the adult generation and that they will in turn support the health costs of children and the elderly when they are in the work force.
When they are in university they might feel that their student loans are burdensome, but those loans equal only about half of the educational investment in them by the society.
If they are a median-income household, they may feel that paying a third of their income for all levels and kinds of taxes is a lot. But their benefits over their lifetime will more than offset the investment.
And if they become wealthy, then they have very likely benefitted from an economy underpinned by government procurement for infrastructure and public services, secured by rule of law. Perhaps they have created their own engineering or construction firm. But they have probably sold their product to public institutions directly or indirectly, or to public institution employees or other people whose jobs are supported by public spending.
Our understanding of our relationship with government would improve if our personal accounts with the Canada Revenue Agency were more like our online banking accounts. They could provide current and historical information on our contributions and withdrawals, provide prorated estimates of the individual costs of public services, like health and education, provide information on any and all government benefits for which we are eligible, and a simple application access. It would be nice to know how much we have paid in taxes over the years, and what benefits we have received. It wouldn't make everyone happy of course, but we would have a better appreciation of our citizenship benefits and obligations.
The millions of dollars that are spent on both sides of the border communicating to citizens that they should vote one way or the other is not building confidence in the government or the democratic system. Redirecting some of that money to continuing, transparent and measurable indicators of the real progress that democracies are making and having these indicators brought to a personal level in our CRA account, could help to reestablish social trust and appreciation of citizenship and government.
Previous Publication Launch: Community-led Development for Climate Justice
Next Atlantic Fellows (LSE) Call for Applications
David Newman says:
I support this completely and we have the technology to do it well. Let's start a movement!
Michael Mott says:
I agree in principle with what you are saying but the elephant in the room is missed in my view, all the reporting in the world about what the government is or is not doing with the money pales in comparison to the looming crisis. I was heartened to see that the City of Vancouver just declared a climate crisis, and are going to act on it.


text:
2011 & 2012 National Champions 2011 & 2012 Region IV Champions 2011 Soccer America Top 20 Clubs 2011 WCDA Champions 2011 Top Drawer National Champions 2011 & 2012 Dallas Cup Champions
Fullerton Rangers Recognized by Fullerton City Council
I wanted to share recent accomplishments of our Boys U96 and Boys U99 teams who will be going to the nationals. They were recognized by the Fullerton City Council this last Tuesday and Coach Jimmy and Coach Christian received official certificates from the Mayor for the teams. We should be proud of these teams and our entire club.
Wear your Ranger jerseys with pride!
Munish Bharadwaja
Director of Business Development and Publicity
Fullerton Rangers Soccer Club
Hello Rangers,
The BU99 team has qualified for the National Championship this year, and will be traveling to Oklahoma in July to represent the Fullerton Rangers and bring home the championship! Additionally the U99 White team is ranked #1 in the State of California, #2 in the nation and are the champions of some of the most prestigious tournaments including the National State Cup Champions, Surf Cup Champions, Regional Champions, and Premier Champions.
Currently, the team has 7 players that have been selected for the Olympic Development Program.
The Boys U96 white team are the first boys U96 team in the Fullerton Rangers 50 year history and it's the most successful one! This team has won 3 National State Cups, two Regional Cups, and the team has won two National Championships. This team is the only team in history to have won the prestigious Youth World Championship the Dallas Cup back to back.
Additionally, 3 players on the team have represented the U.S. Youth National Teams and most recently had a player selected as the best soccer player in America. The success of this team is not only on the field but off. This team will have 14 players playing soccer at the collegiate level, including 5 players that will be attending and playing for CS Fullerton.
A lot of these kids grew up in our program and there will be many more success stories.
Sponsors & Affiliates
Coast Soccer League
Xtreme Soccer
Cal South
Southern California National Premier League
Adidas Soccer
© Fullerton Rangers Soccer Club. All rights reserved.


Pico de gallo is the perfect salsa for the summer! I especially love it on the carne asada my husband makes. It is also great on molletes and is perfect with tortilla chips. It is super easy to make and no cooking is involved. Today I'm going to provide you with a basic recipe that you can adapt to make your own.
At my church I have a friend who adds green onions to her salsa. Also instead of lime juice she uses lemon juice. Her version is so freaking good! What I'm trying to get at is that pico de gallo is very adaptable. So try not to worry too much about the ratios just make it according to your taste. It's also a very beautiful salsa isn't it? Just look at those colors! I really love beautiful colorful fruits and veggies!
I like using roma tomatoes. Sometimes other types of tomatoes can be way too juicy but for me romas are perfect. For the spice factor I use jalapenos but serranos would also work. I highly recommend you try this salsa before summer is over. It's too easy not to try it!
Combine tomatoes,onion,jalapeno, and cilantro together in a bowl.
Season with salt and lime juice to taste and mix well.


text:
Q: Avoid private functions leaking from AngularJS controller I have recently seen situations like this:
app.controller('MainCtrl', ['$scope', 'MyService', function($scope, MyService) {
    $scope.name = 'World';
    var self = this;

    $scope.operationOne = function() {
        MyService.sayHello();
        self.someCommonBehaviour();
    }

    $scope.operationTwo = function() {
        MyService.sayGoodbye();
        self.someCommonBehaviour();
    }

    this.someCommonBehaviour = function() {
    }
}]);

There is some common functionality between functions attached to the scope that is extracted to a function. As we need a reference to the controller to access 'someCommonBehaviour' we append the function to 'this' and store a reference of this in self, so we can access it in the $scope functions (this in the scope is the scope in effect when the function was called).
Functions as 'someCommonBehaviour' can be accessed from the outside (ctrl.someCommonBehaviour()). I think that, at least in the cases that I have seen, the intent is clearly leave those functions as a private concern of the controller. The fact that they can be accessed is an accident.
Moreover, I have seen situations where the programmer is trying to add more logic into an already complicated controller and they fall into the temptation of testing those functions, something that you should not do.
I'm looking for a way of preventing those functions from being accessed from the outside.
I was thinking about IIFE, as they allow you to control the functions that will define the public API of your module (and that is the implementation that I choose for services). It feels weird that the only API that I want for this case is defined by the functions that I add to the scope. So, you would have something like:
(function(module) {
    var controller = function($scope, MyService) {
        $scope.methodOne = function(
        ...
        ...
        return { }
    };
    module.controller('controller', ['$scope','MyService',controller]);
})(angular.module('app');

I think it should work, but it feels so strange returning an empty object.
Am I missing something?. What is the best approach?.

A: Just don't attach it to this. Only the code inside the controller will ever see it.
app.controller('MainCtrl', ['$scope', 'MyService', function($scope, MyService) {
    $scope.name = 'World';
    var self = this;

    $scope.operationOne = function() {
        MyService.sayHello();
        someCommonBehaviour();
    }

    $scope.operationTwo = function() {
        MyService.sayGoodbye();
        someCommonBehaviour();
    }

    // Not accessible outside controller
    function someCommonBehaviour() {

    }
}]);

redpajama_set_name: RedPajamaStackExchange


Set up two 5-meters triangles 10 meters apart. Players are arranged as shown. Players work with one ball. Players change their positions continuously.
P1 starts this soccer drills with a strong pass (1) to P2 who lays the ball back (2) to P1. P2 moves in angle behind the cone and gets the ball back (3) from P1. At the moment P2 approaches, P3 moves farther from P2 and opens space to keep the distance between them. P3 accelerates in space to the front of the ball and gets the pass from P2. Then P3 plays the ball to P4 with one touch or after an accurate receiving. The progression is the same at the other triangle. Players change their positions continuously.


text:
/************************************************
 ff_registry.cpp
 Fodder Factory Monitoring and Control

 (c) Brendan McLearie - bmclearie@mclearie.com

 Component Registry
************************************************/

/************************************************
 Includes
************************************************/
#include <build_config.h>
#include <system.h>
#include <controllers.h>
#include <debug_ff.h>
#include <display.h>
#include <interfaces.h>
#include <inputs.h>
#include <monitors.h>
#include <outputs.h>
#include <registry.h>
#include <rules.h>
#include <schedules.h>
#include <validate.h>
#include <stdlib.h>
#include <string.h>
#include <string_consts.h>
#include <time.h>
#include <utils.h>
#include <block_common.h>

#ifndef PLATFORM_ARDUINO
#include <stdio.h>
#include <errno.h>
#endif //ndef PLATFORM_ARDUINO

#include <HAL.h>
#include <init_config.h>

#ifdef USE_ITCH
#include <out.h>
#endif

/************************************************
 Data Structures
************************************************/

typedef struct FF_STATE_REGISTER {
	//system config and flags
	uint8_t language;
	uint8_t temperature_scale;
	uint8_t time_real_status;
	uint8_t FS_present;
	uint8_t config_valid;
	uint8_t save_event_buffer;
	UIDataSet ui_data;
} FFStateRegister;

/************************************************
 Globals
************************************************/
static uint16_t block_count = 0;	// Increments to assign block_id. TODO remove once static BIDs is implemented
static BlockNode *bll = NULL;		// Block Linked List - variant record block list
static InterfaceNode *ill = NULL;

#ifdef ARDUINO_LCD
	static FFStateRegister sr;
#endif //ARDUINO_LCD

/************************************************
 Functions
************************************************/

void BlockDispatcher(void (*func)(BlockNode*)) {
	BlockNode* block_ptr;

	block_ptr = bll;

	while (block_ptr != NULL) {
		func(block_ptr);
		block_ptr = block_ptr->next;
	}
}

void InterfaceDispatcher(void (*func)(InterfaceNode*)) {
	InterfaceNode* interface_ptr;

	interface_ptr = ill;

	while (interface_ptr != NULL) {
		func(interface_ptr);
		interface_ptr = interface_ptr->next;
	}
}

void SetupInterface(InterfaceNode* b) {
	if (b->status == STATUS_DISABLED_INIT) {
		switch(b->type) {
			case IF_ONEWIRE_BUS:
				InterfaceONEWIRE_BUS_Setup(b);
				break;
			case IF_DS1820B:
				InterfaceDS1820B_Setup(b);
		}
	} else {
		EventMsg(b->id, E_WARNING, M_SETUP_ON_BLOCK_NOT_DISABLED_INIT);
	}
}

void Setup(BlockNode *b) {
	// Called on blocks to configure their initial run-time settings (not config)
	// 	and perform any preliminary setup actions.
	// Blocks that successfully complete setup will change state to STATUS_ENABLED_INIT
	//	which will allow them to be polled in the main operating loop.
	// Blocks are expected to have a status of STATUS_DISABLED_INIT before setup
	//	will be called. This provides a measure of block list consistency by
	//	avoiding run time issues such as blocks referring to other blocks that have
	//	not yet been fully configured. For example, during system load processes,
	// 	a final set post config is to move the blocks to STATUS_DISABLED_INIT. Otherwise,
	//	blocks could become operational prematurely.

	switch (b->cat) {
	case FF_SYSTEM:
		#ifdef UI_ATTACHED
		UpdateUI();
		#endif //UI_ATTACHED
		SystemSetup(b);
		break;
	case FF_INPUT:
		if (b->status == STATUS_DISABLED_INIT) {
			InputSetup(b);
		} else {
			EventMsg(b->id, E_WARNING, M_SETUP_ON_BLOCK_NOT_DISABLED_INIT);
		}
		break;
	case FF_MONITOR:
		if (b->status == STATUS_DISABLED_INIT) {
			MonitorSetup(b);
		} else {
			EventMsg(b->id, E_WARNING, M_SETUP_ON_BLOCK_NOT_DISABLED_INIT);
		}
		break;
	case FF_SCHEDULE: {
		if (b->status == STATUS_DISABLED_INIT) {
			ScheduleSetup(b);
		} else {
			EventMsg(b->id, E_WARNING, M_SETUP_ON_BLOCK_NOT_DISABLED_INIT);
		}
	}
		break;
	case FF_RULE: {
		if (b->status == STATUS_DISABLED_INIT) {
			RuleSetup(b);
		} else {
			EventMsg(b->id, E_WARNING, M_SETUP_ON_BLOCK_NOT_DISABLED_INIT);
		}
	}
		break;
	case FF_CONTROLLER:
		if (b->status == STATUS_DISABLED_INIT) {
			ControllerSetup(b);
		} else {
			EventMsg(b->id, E_WARNING, M_SETUP_ON_BLOCK_NOT_DISABLED_INIT);
		}
		break;
	case FF_OUTPUT:
		if (b->status == STATUS_DISABLED_INIT) {
			OutputSetup(b);
		} else {
			EventMsg(b->id, E_WARNING, M_SETUP_ON_BLOCK_NOT_DISABLED_INIT);
		}
		break;
	default:
		DebugLog(SSS, E_ERROR, M_SET_BCAT_NOT_MATCHED);
		break;
	}
}

void Operate(BlockNode *b) {
	// Calls the appropriate operate function on the block based on its category
	// Called from process dispatcher with each block in the list.
	// Blocks must have a status that is ENABLED (ie < INIT_DISABLED) for
	// 	operate to be called on them.
	// Under system control, blocks may only transition to an ENABLED state as follows:
	//	Block created by AddBlockNode -> STATUS_DISABLED_INIT
	//  STATUS_DISABLED_INIT -> may have Setup called (all other states reject Setup())
	//	Setup -> STATUS_ENABLED_INIT and lower.

	switch (b->cat) {
	case FF_SYSTEM: {
		#ifdef UI_ATTACHED
		UpdateUI();
		#endif
		SystemOperate(b);
		break;
	}
	case FF_INPUT:
		if (b->status < STATUS_DISABLED) {
			InputOperate(b);
		}
		break;
	case FF_MONITOR:
		if (b->status < STATUS_DISABLED) {
			MonitorOperate(b);
		}
		break;
	case FF_SCHEDULE:
		if (b->status < STATUS_DISABLED) {
			ScheduleOperate(b);
		}
		break;
	case FF_RULE:
		if (b->status < STATUS_DISABLED) {
			RuleOperate(b);
		}
		break;
	case FF_CONTROLLER:
		if (b->status < STATUS_DISABLED) {
			ControllerOperate(b);
		}
		break;
	case FF_OUTPUT:
		if (b->status < STATUS_DISABLED) {
			OutputOperate(b);
		}
		break;
	default:
		DebugLog(SSS, E_ERROR, M_OPR_BCAT_NOT_MATCHED);
		break;
	}
}

void InitDisableInterface(InterfaceNode * b) {
	// Change blocks from their current status to
	// STATUS_DISABLED_INIT which means that Operate() will not be
	// 	called on them.
	b->status = STATUS_DISABLED_INIT;
}
void InitDisable(BlockNode* b) {
	// Change blocks from their current status to
	// STATUS_DISABLED_INIT which means that Operate() will not be
	// 	called on them.
	b->status = STATUS_DISABLED_INIT;
}

BlockNode* GetLastBlockAddr(void) {
	BlockNode* block_ptr;

	block_ptr = bll;

	if (block_ptr != NULL) {
		while (block_ptr->next != NULL) {
			block_ptr = block_ptr->next;
		}
		return block_ptr;
	} else {
		return NULL;
	}
}

BlockNode* GetBlockByID(BlockNode *head, uint16_t block_id) {
	// Iterative rather than recursive to save stack space
	// Returns NULL if end of block list reached without matching
	BlockNode* walker;
	walker = head;
	while(walker != NULL) {
		if(walker->id == block_id) {
			return walker;
		} else {
			walker = walker->next;
		}
	}
	return walker;
}

InterfaceNode* GetInterfaceByID(InterfaceNode *head, uint16_t block_id) {
	// Iterative rather than recursive to save stack space
	// Returns NULL if end of block list reached without matching
	InterfaceNode* walker;
	walker = head;
	while(walker != NULL) {
		if(walker->id == block_id) {
			return walker;
		} else {
			walker = walker->next;
		}
	}
	return walker;
}

InterfaceNode* GetInterfaceByID(uint16_t id) {
	InterfaceNode* walker;
	walker = ill;
	while(walker != NULL) {
		if(walker->id == id) {
			return walker;
		} else {
			walker = walker->next;
		}
	}
	return walker;
}

uint16_t GetInterfaceIDByLabel(const char* label) {
	// Returns 0 if end of block list reached without matching
	InterfaceNode* walker;
	walker = ill;
	while(walker != NULL) {
		if(strcmp(walker->label, label) == 0) {
			return walker->id;
		} else {
			walker = walker->next;
		}
	}
	return 0;
}

uint8_t SetCommand(uint16_t block_id, uint8_t cmd_msg) {
	BlockNode *b;
	b = GetBlockByID(bll, block_id);
	if (b) {
		if (b->cat == FF_OUTPUT) {
			b->settings.out.command = cmd_msg;
			return cmd_msg;
		} else {
			DebugLog(b->id, E_ERROR, M_CMD_TO_BLOCK_NOT_OUTPUT);
			return M_FF_ERROR;
		}
	} else {
		DebugLog(SSS, E_ERROR, M_CMD_BID_NULL);
		return M_FF_ERROR;
	}
}

uint8_t IsActive(uint16_t block_id) {
	BlockNode *b;
	b = GetBlockByID(bll, block_id);
	if (b) {
		return b->active;
	} else {
		DebugLog(SSS, E_ERROR, M_IA_NULL);
		return M_FF_ERROR;
	}
}

float GetFVal(uint16_t block_id) {
	BlockNode *b;
	b = GetBlockByID(bll, block_id);
	if (b) {
		return b->f_val;
	} else {
		DebugLog(SSS, E_ERROR, M_GFV_NULL);
		return M_FF_ERROR;
	}
}

uint8_t GetBVal(uint16_t block_id) {
	BlockNode *b;
	b = GetBlockByID(bll, block_id);
	if (b) {
		return b->bool_val;
	} else {
		DebugLog(SSS, E_ERROR, M_GBV_NULL);
		return M_FF_ERROR;
	}
}

uint16_t GetBlockIDByLabel(const char* label, bool report_fail) {
	// Within core code this is used to ensure complete internal block list
	// consistency and should report error ie called with report_fail = true
	// Within itch this is being called to check for existence of complete
	// labels in the parser and is called with report_fail = false for normal
	// itch behaviour when looking up partial labels
	BlockNode* b;
	InterfaceNode* i;
	char debug_msg[MAX_LOG_LINE_LENGTH];

	b = bll;
	i = ill;

	while (b != NULL) {
		if (strcmp(b->label, label) == 0) {
			return b->id;
		} else {
			b = b->next;
		}
	}
	while (i != NULL) {
		if (strcmp(i->label, label) == 0) {
			return i->id;
		} else {
			i = i->next;
		}
	}

	if (report_fail == true) {
		char msg_str[31];
		strcpy_hal(msg_str, F("ERROR: B-Label Not Found: [%s]"));
		sprintf(debug_msg, msg_str, label);
		DebugLog(debug_msg);
		EventMsg(SSS, E_ERROR, M_BLOCK_ID_NOT_FOUND);
	}
	return M_FF_ERROR;
}

char const* GetBlockLabelString(uint16_t block_id) {
	// Return a pointer to the label string of the block
	// identified by block_id

	BlockNode* b;
	InterfaceNode *i;
	//char debug_msg[MAX_LOG_LINE_LENGTH];
	//char msg_str[30];
	b = bll;
	i = ill;

	/*
	if (block_id == BLOCK_ID_NA) {
		return "NA";
	}

	if (block_id == UINT16_INIT) {
		return "\0";
	}
	 */

	while (b != NULL) {
		if (b->id == block_id) {
				return b->label;
		}
		b = b->next;
	}

	// not found in bll

	while (i != NULL) {
		if (i->id == block_id) {
				return i->label;
		}
		i = i->next;
	}

	/*
	// Block Label not found
	if (block_id == SSS) {
		// Possibly pre-config message
		//return "SYSTEM-NOCONFIG";
		//XXX
		return NULL;
	}
	*/

	/*
	strcpy_hal(msg_str, F("ERROR: B-ID Not Found: [%d]"));
	sprintf(debug_msg, msg_str, block_id);
	DebugLog(debug_msg);
	EventMsg(SSS, E_ERROR, M_BLOCK_ID_NOT_FOUND);
	*/
	return NULL;
}

BlockNode* GetBlockListHead(void) {
	return bll;
}

InterfaceNode* GetInterfaceListHead(void) {
	return ill;
}

BlockNode* NewBlockNode(uint8_t block_cat, const char *block_label) {
	BlockNode* new_block;

	// common settings and setting holders for all blocks
	new_block = (BlockNode *) malloc(sizeof(BlockNode));
	if (new_block == NULL) {
		DebugLog(SSS, E_STOP, M_ADDBLOCK_ERROR);
		while (1)
			;
	} else {
		//			DebugLog("(AddBlock) malloc OK");
	}
	new_block->next = NULL;
	new_block->label = NULL;
	#ifndef	EXCLUDE_DISPLAYNAME
		new_block->display_name = NULL;
	#endif
	#ifndef EXCLUDE_DESCRIPTION
		new_block->description = NULL;
	#endif

	new_block->cat = block_cat;
	new_block->type = UINT8_INIT;

	// initialise operational, run-time block data
	new_block->active = 0;
	new_block->bool_val = 0;
	new_block->int_val = INT32_INIT;
	new_block->f_val = FLOAT_INIT;
	//new_block->last_update = UINT32_INIT;
	//new_block->last_logged = UINT32_INIT;
	// New blocks are disabled by default
	new_block->status = STATUS_DISABLED_INIT;

	if (block_cat != FF_GENERIC_BLOCK) {

		if (block_cat == FF_SYSTEM) {
			new_block->id = SSS;
		} else {
			new_block->id = BLOCK_ID_BASE + block_count;
			block_count++;
		}

		if(block_label != NULL) {
			// XXX add null checks
			new_block->label = (char *)malloc( (strlen(block_label)+1) * sizeof(char) );
			strcpy(new_block->label, block_label);
		} else {
			new_block->label = NULL;
		}

#ifndef	EXCLUDE_DISPLAYNAME
		//new_block->display_name[0] = '\0';
		new_block->display_name = NULL;
#endif
#ifndef EXCLUDE_DESCRIPTION
		//new_block->description[0] = '\0';
		new_block->description = NULL;
#endif

		switch (block_cat) {
			case FF_SYSTEM:
				new_block->settings.sys.language = ENGLISH;
				new_block->settings.sys.temp_scale = UNIT_ERROR;
				new_block->settings.sys.week_start = SUN;
				new_block->settings.sys.start_delay = 0;
				break;
			case FF_INPUT:
				new_block->settings.in.interface = BLOCK_ID_INIT;
				//new_block->settings.in.if_num = UINT8_INIT;
				new_block->settings.in.log_rate = UINT16_INIT;
				new_block->settings.in.poll_rate = UINT16_INIT;
				new_block->settings.in.last_polled = UINT32_INIT;
				new_block->settings.in.last_logged = UINT32_INIT;

				new_block->settings.in.data_units = UNIT_ERROR;
				new_block->settings.in.data_type = UINT8_INIT;
				break;
			case FF_MONITOR:
				new_block->settings.mon.input1 = BLOCK_ID_INIT;
				new_block->settings.mon.input2 = BLOCK_ID_INIT;
				new_block->settings.mon.input3 = BLOCK_ID_INIT;
				new_block->settings.mon.input4 = BLOCK_ID_INIT;
				new_block->settings.mon.act_val = FLOAT_INIT;
				new_block->settings.mon.deact_val = FLOAT_INIT;
				break;
			case FF_SCHEDULE:
				for (int i = 0; i < LAST_DAY; i++)
					new_block->settings.sch.days[i] = UINT8_INIT;
				new_block->settings.sch.time_start = UINT32_INIT;
				new_block->settings.sch.time_end = UINT32_INIT;
				new_block->settings.sch.time_duration = 0;
				new_block->settings.sch.time_repeat = 0;
				break;
			case FF_RULE:
				new_block->settings.rl.param1 = BLOCK_ID_INIT;
				new_block->settings.rl.param2 = BLOCK_ID_INIT;
				new_block->settings.rl.param3 = BLOCK_ID_INIT;
				new_block->settings.rl.param_not = BLOCK_ID_INIT;
				break;
			case FF_CONTROLLER:
				new_block->settings.con.rule = BLOCK_ID_INIT;
				new_block->settings.con.output = BLOCK_ID_INIT;
				new_block->settings.con.act_cmd = CMD_ERROR;
				new_block->settings.con.deact_cmd = CMD_ERROR;
				break;
			case FF_OUTPUT:
				new_block->settings.out.interface = IF_ERROR;
				new_block->settings.out.if_num = UINT8_INIT;
				new_block->settings.out.command = CMD_INIT;
				break;
		} //switch
	} // != FF_GENERIC_BLOCK

	return new_block;
}

InterfaceNode* NewInterfaceNode(uint8_t if_type, const char *label) {
	InterfaceNode* new_if;

	new_if = (InterfaceNode *) malloc(sizeof(InterfaceNode));
	if (new_if == NULL) {
		DebugLog(SSS, E_STOP, M_ADDBLOCK_ERROR);
		while (1)
			;
	}
	new_if->next = NULL;
	new_if->label = NULL;
	#ifndef	EXCLUDE_DISPLAYNAME
	new_if->display_name = NULL;
	#endif
	#ifndef EXCLUDE_DESCRIPTION
	new_if->description = NULL;
	#endif

	new_if->type = if_type;
	new_if->status = STATUS_DISABLED_INIT;

	new_if->id = BLOCK_ID_BASE + block_count;
	block_count++;

	if (label != NULL) {
		// XXX add null checks
		new_if->label = (char *) malloc((strlen(label) + 1) * sizeof(char));
		strcpy(new_if->label, label);
	} else {
		new_if->label = NULL;
	}

	switch (new_if->type) {
		case IF_WIFI: {
			//"IF_WIFI"
			InterfaceWIFI* ifs; 	// IF Settings
			ifs = (InterfaceWIFI *)malloc(sizeof(InterfaceWIFI));
			if (ifs) {
				//ifs->gateway_staic = {0, 0, 0, 0};
				//ifs->ip_static = {0, 0, 0, 0};
				//ifs->netmask_static = {0, 0, 0, 0};
				//ifs->static_address = 0;
				//ifs->wifi_ssid = "";
				//ifs->wpa_psk = "";
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_ETHERNET: {
			//"IF_ETHERNET"
			InterfaceETHERNET* ifs; 	// IF Settings
			ifs = (InterfaceETHERNET *)malloc(sizeof(InterfaceETHERNET));
			if (ifs) {
				//ifs->ip_gateway = (0, 0, 0, 0);
				//ifs->ip_static = {0, 0, 0, 0};
				//ifs->ip_netmask = {0, 0, 0, 0};
				ifs->static_address = 0;
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_PWM_IN: {
			//"IF_PWM_IN"
			InterfacePWM_IN* ifs; 	// IF Settings
			ifs = (InterfacePWM_IN *)malloc(sizeof(InterfacePWM_IN));
			if (ifs) {
				// Field initialisers here
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_PWM_OUT: {
			//"IF_PWM_OUT"
			InterfacePWM_OUT* ifs; 	// IF Settings
			ifs = (InterfacePWM_OUT *)malloc(sizeof(InterfacePWM_OUT));
			if (ifs) {
				// Field initialisers here
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_PPM_IN: {
			//"IF_PPM_IN"
			InterfacePPM_IN* ifs; 	// IF Settings
			ifs = (InterfacePPM_IN *)malloc(sizeof(InterfacePPM_IN));
			if (ifs) {
				// Field initialisers here
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_PPM_OUT: {
			//"IF_PPM_OUT"
			InterfacePPM_OUT* ifs; 	// IF Settings
			ifs = (InterfacePPM_OUT *)malloc(sizeof(InterfacePPM_OUT));
			if (ifs) {
				// Field initialisers here
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_DS1820B: {
			//"IF_DS1820B"
			InterfaceDS1820B* ifs; 	// IF Settings
			ifs = (InterfaceDS1820B *)malloc(sizeof(InterfaceDS1820B));
			if (ifs) {
				// Field initialisers here
				ifs->bus_pin = UINT8_INIT;
				DallasAddressStringToArray("00:00:00:00:00:00:00:00", ifs->dallas_address);
				ifs->in_progress = 0;
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_ONEWIRE_BUS: {
			//"IF_ONEWIRE_BUS"
			InterfaceONEWIRE_BUS* ifs; 	// IF Settings
			ifs = (InterfaceONEWIRE_BUS *)malloc(sizeof(InterfaceONEWIRE_BUS));
			if (ifs) {
				ifs->bus_pin = UINT8_INIT;
				ifs->device_count = UINT8_INIT;
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_DIG_PIN_IN: {
			//"IF_DIG_PIN_IN"
			InterfaceDIG_PIN_IN* ifs; 	// IF Settings
			ifs = (InterfaceDIG_PIN_IN *)malloc(sizeof(InterfaceDIG_PIN_IN));
			if (ifs) {
				// Field initialisers here
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_DIG_PIN_OUT: {
			//"IF_DIG_PIN_OUT"
			InterfaceDIG_PIN_OUT* ifs; 	// IF Settings
			ifs = (InterfaceDIG_PIN_OUT *)malloc(sizeof(InterfaceDIG_PIN_OUT));
			if (ifs) {
				// Field initialisers here
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_VED_VOLTAGE: {
			//"IF_VED_VOLTAGE"
			InterfaceVED_VOLTAGE* ifs; 	// IF Settings
			ifs = (InterfaceVED_VOLTAGE *)malloc(sizeof(InterfaceVED_VOLTAGE));
			if (ifs) {
				// Field initialisers here
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_VED_CURRENT: {
			//"IF_VED_CURRENT"
			InterfaceVED_CURRENT* ifs; 	// IF Settings
			ifs = (InterfaceVED_CURRENT *)malloc(sizeof(InterfaceVED_CURRENT));
			if (ifs) {
				// Field initialisers here
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_VED_POWER: {
			//"IF_VED_POWER"
			InterfaceVED_POWER* ifs; 	// IF Settings
			ifs = (InterfaceVED_POWER *)malloc(sizeof(InterfaceVED_POWER));
			if (ifs) {
				// Field initialisers here
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_VED_SOC: {
			//"IF_VED_SOC"
			InterfaceVED_SOC* ifs; 	// IF Settings
			ifs = (InterfaceVED_SOC *)malloc(sizeof(InterfaceVED_SOC));
			if (ifs) {
				// Field initialisers here
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		case IF_HW_SERIAL: {
			//"IF_VED_SOC"
			InterfaceHW_SERIAL* ifs; 	// IF Settings
			ifs = (InterfaceHW_SERIAL *)malloc(sizeof(InterfaceHW_SERIAL));
			if (ifs) {
				// Field initialisers here
				new_if->IFSettings = ifs;
			} else {
				EventMsg(SSS, E_STOP, M_ADDIFS_MALLOC_NULL);
				#ifdef PLATFORM_ARDUINO
					while(1);
				#endif
				#ifdef PLATFORM_LINUX
					exit(-1);
				#endif
			}
			break;
		}
		default:
			return 0; // catch-all error
	}
	return new_if;
}

uint8_t GetBlockCatIdxByBID(uint16_t bid) {
	BlockNode* b;
	InterfaceNode* i;

	b = bll;
	i = ill;

	while (b != NULL) {
		if (b->id == bid) {
			return b->cat;
		} else {
			b = b->next;
		}
	}
	while (i != NULL) {
		if (i->id == bid)  {
			return FF_INTERFACE;
		} else {
			i = i->next;
		}
	}
	return FF_ERROR_CAT;
}

uint8_t GetBlockCatIdxByBlockCatName(char* name) {
	uint8_t id = LAST_BLOCK_CAT - 1;
	char cat_name[MAX_LABEL_LENGTH];

 	for (; id > 0; id--) {
		strcpy_hal(cat_name, block_cat_strings[id].text);
		if (strcasecmp(name, cat_name) == 0) {
			return id;
		}
	}
	return id;
}

uint8_t DeleteBlockByID(uint16_t bid) {
	BlockNode* bwalker = bll;
	BlockNode* bprevious = bll;

	InterfaceNode* iwalker = ill;
	InterfaceNode* iprevious = ill;

	// Check normal block list first
	while (bwalker != NULL) {
		if(bwalker->id == bid) {
			//found - delete it
			if (bwalker == bll) {
				//special case - head of list
				bll = bwalker->next;
				free(bwalker->label);
				free(bwalker);
				return 1;
			} else {
				//delete and relink previous to next
				bprevious->next = bwalker->next;
				free(bwalker->label);
				free(bwalker);
				return 1;
			}
		} else {
			// wasn't that one, move to next keeping track of bprevious
			bprevious = bwalker;
			bwalker = bwalker->next;
		}
	}
	if (bwalker == NULL) {
		// Search interface list
		while (iwalker != NULL) {
			if(iwalker->id == bid) {
				//found - delete it
				if (iwalker == ill) {
					//special case - head of list
					ill = iwalker->next;
					free(iwalker->label);
					free(iwalker->IFSettings);
					free(iwalker);
					return 1;
				} else {
					//delete and relink previous to next
					iprevious->next = iwalker->next;
					free(iwalker->label);
					free(iwalker->IFSettings);
					free(iwalker);
					return 1;
				}
			} else {
				// wasn't that one, move to next keeping track of previous
				iprevious = iwalker;
				iwalker = iwalker->next;
			}
		}

	}
	return 0; // ID not found
}

uint8_t DeleteBlockByLabel(const char *label) {
	// In an edge case of a duplicate block ID with a different label
	// this deletes based on label search rather than a label lookup
	// for ID and then delete by ID
	BlockNode* bwalker = bll;
	BlockNode* bprevious = bll;

	InterfaceNode* iwalker = ill;
	InterfaceNode* iprevious = ill;

	// Check normal block list first
	while (bwalker != NULL) {
		if(strcmp(bwalker->label, label) == 0) {
			//found - delete it
			if (bwalker == bll) {
				//special case - head of list
				bll = bwalker->next;
				free(bwalker->label);
				free(bwalker);
				return 1;
			} else {
				//delete and relink previous to next
				bprevious->next = bwalker->next;
				free(bwalker->label);
				free(bwalker);
				return 1;
			}
		} else {
			// wasn't that one, move to next keeping track of previous
			bprevious = bwalker;
			bwalker = bwalker->next;
		}
		if (bwalker == NULL) {
			// search the interface list
			while (iwalker != NULL) {
				if(strcmp(iwalker->label, label) == 0) {
					//found - delete it
					if (iwalker == ill) {
						//special case - head of list
						ill = iwalker->next;
						free(iwalker->label);
						free(iwalker);
						return 1;
					} else {
						//delete and relink previous to next
						iprevious->next = iwalker->next;
						free(iwalker->label);
						free(iwalker);
						return 1;
					}
				} else {
					// wasn't that one, move to next keeping track of previous
					iprevious = iwalker;
					iwalker = iwalker->next;
				}
			}
		}
	}
	return 0; //error
}

BlockNode* AddBlock(uint8_t block_cat, const char *block_label) {
	// Low level function to add a block to the list
	// Note: no checking for duplicates or existence.
	// Use higher level function ConfigureBlock for safer application
	// Implementation: to save stack memory, iterate down the block list
	//  and only call AddBlockNode function once at the end of the list

	if (bll == NULL) {
		bll = NewBlockNode(block_cat, block_label);
		return bll;
	} else {

		BlockNode* walker = bll;
		while(walker->next != NULL) {
			walker = walker->next;
		}
		walker->next = NewBlockNode(block_cat, block_label);
		return walker->next;
	}
}

InterfaceNode* AddInterface(uint8_t if_type, const char *label) {
	// Low level function to add an interface to the list
	// Note: no checking for duplicates or existence.
	// Use higher level function ConfigureIFBlock for safer application
	// Implementation: to save stack memory, iterate down the block list
	//  and only call AddBlockNode function once at the end of the list

	if (ill == NULL) {
		ill = NewInterfaceNode(if_type, label);
		return ill;
	} else {

		InterfaceNode* walker = ill;
		while(walker->next != NULL) {
			walker = walker->next;
		}
		walker->next = NewInterfaceNode(if_type, label);
		return walker->next;
	}
}

char* UpdateBlockLabel(BlockNode* b, const char * block_label) {
	// Update the label of a block and adjust its memory use
	// Possible calling value combinations:
	// b->label == NULL and block_label != NULL - malloc (new label to previously NULL label)
	// b->label == NULL and block_label == NULL - do nothing (NULL label to existing NULL label)
	// b->label != NULL and block_label == NULL - free b->label (Existing label to be NULL'd and freed)
	// b->label != NULL and block_label != NULL - realloc b->label (Different label - free and re-malloc)

	if (b->label == NULL) {
		// not previously malloced
		if (block_label != NULL) {
			b->label = (char *)malloc( (strlen(block_label)+1) * sizeof(char) );
			// XXX add null check and debug throw
			strcpy(b->label, block_label);
		} else {
			// block_label is NULL
			return NULL;
		}
	} else {
		// b->block label already assigned
		if(block_label == NULL) {
			// update to NULL
			free(b->label);
			b->label = NULL;
			return NULL;
		} else {
			// XXX realloc fails at link time. Workaround: free and malloc again
			free(b->label);
			b->label = (char *)malloc( (strlen(block_label)+1) * sizeof(char) );
			// XXX add null check and debug throw
			strcpy(b->label, block_label);
		}
	}
	return b->label;
}

#ifndef EXCLUDE_DISPLAYNAME
char* UpdateDisplayName(BlockNode* b, const char * display_name) {
	// Update the display_name of a block and adjust its memory use
	// Possible calling value combinations:
	// b->display_name == NULL and display_name != NULL - malloc (new display_name to previously NULL display_name)
	// b->display_name == NULL and display_name == NULL - do nothing (NULL display_name to existing NULL display_name)
	// b->display_name != NULL and display_name == NULL - free b->display_name (Existing display_name to be NULL'd and freed)
	// b->display_name != NULL and display_name != NULL - realloc b->display_name (Different display_name - free and re-malloc)

	if (b->display_name == NULL) {
		// not previously malloced
		if (display_name != NULL) {
			b->display_name = (char *)malloc( (strlen(display_name)+1) * sizeof(char) );
			// XXX add null check and debug throw
			strcpy(b->display_name, display_name);
		} else {
			// block_label is NULL
			return NULL;
		}
	} else {
		// b->block label already assigned
		if(display_name == NULL) {
			// update to NULL
			free(b->display_name);
			b->display_name = NULL;
			return NULL;
		} else {
			// XXX realloc fails at link time. Workaround: free and malloc again
			free(b->display_name);
			b->display_name = (char *)malloc( (strlen(display_name)+1) * sizeof(char) );
			// XXX add null check and debug throw
			strcpy(b->display_name, display_name);
		}
	}
	return b->display_name;
}
#endif

#ifndef EXCLUDE_DESCRIPTION
char* UpdateDescription(BlockNode* b, const char * description) {
	// Update the description of a block and adjust its memory use
	// Possible calling value combinations:
	// b->description == NULL and description != NULL - malloc (new description to previously NULL description)
	// b->description == NULL and description == NULL - do nothing (NULL description to existing NULL description)
	// b->description != NULL and description == NULL - free b->description (Existing description to be NULL'd and freed)
	// b->description != NULL and description != NULL - realloc b->description (Different description - free and re-malloc)

	if (b->description == NULL) {
		// not previously malloced
		if (description != NULL) {
			b->description = (char *)malloc( (strlen(description)+1) * sizeof(char) );
			// XXX add null check and debug throw
			strcpy(b->description, description);
		} else {
			// block_label is NULL
			return NULL;
		}
	} else {
		// b->block label already assigned
		if(description == NULL) {
			// update to NULL
			free(b->description);
			b->description = NULL;
			return NULL;
		} else {
			// XXX realloc fails at link time. Workaround: free and malloc again
			free(b->description);
			b->description = (char *)malloc( (strlen(description)+1) * sizeof(char) );
			// XXX add null check and debug throw
			strcpy(b->description, description);
		}
	}
	return b->description;
}
#endif

BlockNode* GetBlockNodeByLabel(BlockNode *head, const char *block_label) {
	// re-written iteratively

	BlockNode* walker;
	walker = head;
	while(walker != NULL) {
		if (strcmp(walker->label, block_label) == 0) {
			return walker;
		} else {
			walker = walker->next;
		}
	}
	return walker;
}

BlockNode* GetBlockByLabel(const char *block_label) {
	return GetBlockNodeByLabel(bll, block_label);
}

InterfaceNode* GetInterfaceNodeByLabel(InterfaceNode *head, const char* label) {
	InterfaceNode* walker;
	walker = head;
	while(walker != NULL) {
		if (strcmp(walker->label, label) == 0) {
			return walker;
		} else {
			walker = walker->next;
		}
	}
	return walker;
}

InterfaceNode* GetInterfaceByLabel(const char* label) {
	return GetInterfaceNodeByLabel(ill, label);
}

uint16_t GetInterfaceWithMatchingDallas(uint8_t addr[8]) {
	// Scan the interface list searching IF_DS1820B types
	// compare the address and if the same return the block_id
	// else return 0
	InterfaceNode *b;
	InterfaceDS1820B *ifs;
	b = ill;
	while (b != NULL) {
		if (b->type == IF_DS1820B) {
			ifs = (InterfaceDS1820B *)b->IFSettings;
			if (DallasCompare(addr, ifs->dallas_address) == 0) {
				return b->id;
			}
		}
		b = b->next;
	}
	return 0;
}

void DropBlockList(void) {
	BlockNode* block_ptr;
	BlockNode* next_ptr;

	block_ptr = bll;

	while (block_ptr != NULL) {
		next_ptr = block_ptr->next;
		free(block_ptr->label);
		#ifndef	EXCLUDE_DISPLAYNAME
			free(block_ptr->display_name);
		#endif
		#ifndef EXCLUDE_DESCRIPTION
			free(block_ptr->description);
		#endif
		free(block_ptr);
		block_ptr = next_ptr;
	}
	bll = NULL;
}

void DropInterfaceList(void) {
	InterfaceNode* block_ptr;
	InterfaceNode* next_ptr;

	block_ptr = ill;

	while (block_ptr != NULL) {
		next_ptr = block_ptr->next;
		free(block_ptr->label);
		free(block_ptr->IFSettings);
		#ifndef	EXCLUDE_DISPLAYNAME
			free(block_ptr->display_name);
		#endif
		#ifndef EXCLUDE_DESCRIPTION
			free(block_ptr->description);
		#endif
		free(block_ptr);
		block_ptr = next_ptr;
	}
	ill = NULL;
}

/********************************************************************************************
 * ITCH Integration Handlers
 ********************************************************************************************/

uint8_t RegLookupBlockLabel(const char* lookup_string) {
	return GetBlockIDByLabel(lookup_string, false);
}

void RegShowBlocks(void(*Callback)(const char *)) {
	// XXX this whole business of calculating field widths and manipulating
	// endless strings is complete overkill merely to optimise a diagnostic
	// display.
	// Error checking on valid ranges is however critical - especially
	//  when reading out blocks that have a config file mismatched to firmware
	//  version.

	BlockNode* b;
	InterfaceNode* i;

	char out[MAX_LOG_LINE_LENGTH];
	char fmt[9];

	uint8_t w_id = 0;
	uint8_t w_label = 0;
	uint8_t w_cat = 0;
	uint8_t w_type = 0;
	uint8_t w_status = 0;
	uint8_t w_active = 0;

	// Calculate min field widths
	// Common to all
	w_id = 4;		// nnnn
	w_active = 3;	// "OFF: For Heading "ACT"

	w_cat = strlen_hal(block_cat_strings[FF_INTERFACE].text);

	i = ill;
	while (i != NULL) {
		// Label is in RAM
		if (strlen(i->label) > w_label) {
			w_label = strlen(i->label);
		}
		if (i->type < LAST_INTERFACE) {
			if (strlen_hal(interface_type_strings[i->type].text) > w_type) {
				w_type = strlen_hal(interface_type_strings[i->type].text);
			}
		} else {
			w_type = strlen_hal(interface_type_strings[IF_ERROR].text);
		}

		if (i->status < LAST_STATUS) {
			if (strlen_hal(status_strings[i->status].text) > w_status) {
				w_status = strlen_hal(status_strings[i->status].text);
			}
		} else {
			w_status = strlen_hal(status_strings[STATUS_ERROR].text);
		}

		i = i->next;
	}

	b = bll;
	while (b != NULL) {
		if (b->cat < LAST_BLOCK_CAT) {
			if (strlen_hal(block_cat_strings[b->cat].text) > w_cat) {
				w_cat = strlen_hal(block_cat_strings[b->cat].text);
			}
		} else {
			w_cat = strlen_hal(block_cat_strings[FF_ERROR_CAT].text);
		}

		// label is in RAM
		if (strlen(b->label) > w_label) {
			w_label = strlen(b->label);
		}

		if (b->type < LAST_BLOCK_TYPE) {
			if (strlen_hal(block_type_strings[b->type].text) > w_type) {
				w_type = strlen_hal(block_type_strings[b->type].text);
			}
		} else {
			w_type = strlen_hal(block_type_strings[BT_ERROR].text);
		}

		if (b->status < LAST_STATUS) {
			if (strlen_hal(status_strings[b->status].text) > w_status) {
				w_status = strlen_hal(status_strings[b->status].text);
			}
		} else {
			w_status = strlen_hal(status_strings[LAST_STATUS].text);
		}

		b = b->next;
	}

	b = bll;
	i = ill;
	if ((b != NULL) || (i != NULL)) {
		strcpy_hal(out, F("\t"));
		strcatpad_hal(out, F("BID"), (w_id +2));
		strcatpad_hal(out, F("LABEL"), (w_label +2));
		strcatpad_hal(out, F("ACT"), (w_active +2));
		strcatpad_hal(out, F("CAT"), (w_cat +2));
		strcatpad_hal(out, F("TYPE"), (w_type +2));
		strcatpad_hal(out, F("STATUS"), (w_status +2));
		Callback(out);
	}

	i = ill;
	if (i == NULL) {
		strcpy_hal(out, F("No Interfaces"));
		Callback(out);
	} else {
		while (i != NULL) {
			// id is in RAM on all platforms. fmt from PROGMEM on AVR
			strcpy_hal(fmt, F("\t%-4d  "));
			sprintf(out, fmt, i->id);
			// TODO - write a proper int to string func that pads

			// label is in RAM
			strcatpad(out, i->label, w_label+2);

			// Active is NA for Interfaces
			strcatpad_hal(out, F("NA"), w_active+2);

			// Category string in PROGMEM on AVR
			strcatpad_hal(out, block_cat_strings[FF_INTERFACE].text, w_cat+2);

			// type string in PROGMEM on AVR
			if (i->type < LAST_INTERFACE) {
				strcatpad_hal(out, interface_type_strings[i->type].text, w_type+2);
			} else {
				strcatpad_hal(out, interface_type_strings[IF_ERROR].text, w_type+2);
			}

			// status string in PROGMEM on AVR
			if (i->status < LAST_STATUS) {
				strcatpad_hal(out, status_strings[i->status].text, w_status);
			} else {
				strcatpad_hal(out, status_strings[STATUS_ERROR].text, w_status);
			}

			Callback(out);
			i = i->next;
		}
	}

	b = bll;
	if (b == NULL) {
		strcpy_hal(out, F("No Blocks"));
		Callback(out);
	} else {
		while(b != NULL) {
			// id is in RAM on all platforms. fmt from PROGMEM on AVR
			strcpy_hal(fmt, F("\t%-4d  "));
			sprintf(out, fmt, b->id);

			// label is in RAM
			strcatpad(out, b->label, w_label+2);

			// Active is NA for Interfaces
			if (b->active) {
				strcatpad_hal(out, F("ON"), w_active+2);
			} else {
				strcatpad_hal(out, F("OFF"), w_active+2);
			}

			// Category string in PROGMEM on AVR
			if (b->cat < LAST_BLOCK_CAT) {
				strcatpad_hal(out, block_cat_strings[b->cat].text, w_cat+2);
			} else {
				strcatpad_hal(out, block_cat_strings[FF_ERROR_CAT].text, w_cat+2);
			}

			// type string in PROGMEM on AVR
			if (b->type < LAST_BLOCK_TYPE) {
				strcatpad_hal(out, block_type_strings[b->type].text, w_type+2);
			} else {
				strcatpad_hal(out, block_type_strings[BT_ERROR].text, w_type+2);
			}

			// status string in PROGMEM on AVR
			if (b->status < LAST_STATUS) {
				strcatpad_hal(out, status_strings[b->status].text, w_status);
			} else {
				strcatpad_hal(out, status_strings[STATUS_ERROR].text, w_status);
			}

			Callback(out);
			b = b->next;
		}
	}
}

void RegShowSystem(void(*Callback)(const char *)) {
	RegShowBlockByID(SSS, Callback);
}

void RegShowBlockByLabel(const char* block_label, void(*Callback)(const char *)) {
	RegShowBlockByID(GetBlockIDByLabel(block_label, true), Callback);
}

void RegShowBlockByID(uint16_t id, void(*Callback)(const char *)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	char fmt_str[MAX_LABEL_LENGTH];

	BlockNode *b;
	InterfaceNode *i;

	uint8_t bcat = GetBlockCatIdxByBID(id);

	if (bcat == FF_ERROR_CAT) {
		strcpy_hal(fmt_str, F("Error: %d is not a valid block ID"));
		sprintf(out_str, fmt_str, id);
		Callback(out_str);
	} else {
		switch (bcat) {
			case FF_INTERFACE:
				i = GetInterfaceByID(ill, id);
				InterfaceShow(i, Callback);
				break;
			case FF_SYSTEM:
				b = GetBlockByID(bll, id);
				SystemShow(b, Callback);
				break;
			case FF_INPUT:
				b = GetBlockByID(bll, id);
				InputShow(b, Callback);
				break;
			case FF_MONITOR:
				b = GetBlockByID(bll, id);
				MonitorShow(b, Callback);
				break;
			case FF_SCHEDULE:
				b = GetBlockByID(bll, id);
				ScheduleShow(b, Callback);
				break;
			case FF_RULE:
				b = GetBlockByID(bll, id);
				RuleShow(b, Callback);
				break;
			case FF_CONTROLLER:
				b = GetBlockByID(bll, id);
				ControllerShow(b, Callback);
				break;
			case FF_OUTPUT:
				b = GetBlockByID(bll, id);
				OutputShow(b, Callback);
				break;
		}
	}
}

void RegShowMemory(void(*Callback)(const char *)) {
	(void)Callback;
	char out_str[MAX_MESSAGE_STRING_LENGTH];
	GetMemPointers(out_str);
	ITCHWriteLine(out_str);
}

void RegSetCommandOnBlockLabel(const char* block_label, uint16_t command, void(*Callback)(const char *)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	uint16_t block_id;
	char fmt_str[35];

	block_id = GetBlockIDByLabel(block_label, true);
	if (block_id == M_FF_ERROR) {
		strcpy_hal(fmt_str, F("Block: %s not found"));
		sprintf(out_str, fmt_str, block_label);
		Callback(out_str);
	} else {
		RegSetCommandOnBlockID(block_id, command, Callback);
	}
}

void RegIFOneWireScanBID(int16_t param1_int, void(*Callback)(const char*)) {
	(void)Callback; // not used
	InterfaceNode *i;
	i = GetInterfaceByID(ill, param1_int);
	if (i) {
		ScanAndMatchDallasSensors(i, 1);
	} else {
		ITCHWriteLine(F("Unknown Interface ID"));
	}
}

void RegIFOneWireScanLabel(char* BLOCK_LABEL, void(*Callback)(const char*)) {
	(void)Callback; // not used
	uint16_t id;
	id = GetInterfaceIDByLabel(BLOCK_LABEL);
	if (id) {
		RegIFOneWireScanBID(id, WriteLineCallback);
	} else {
		ITCHWriteLine(F("Unknown Interface Label"));
	}
}

void RegIFOneWireAssignBID(int16_t param1_int, int16_t param2_int, void(*Callback)(const char*)) {
	(void)Callback; // not used
	InterfaceNode *s;
	InterfaceNode *t;
	s = GetInterfaceByID(ill, param1_int);
	t = GetInterfaceByID(ill, param2_int);
	if (s && t) {
		AssignDallasSensor(s, t, 1);
	} else {
		ITCHWriteLine(F("Unknown Interface ID"));
	}
}

void RegIFDS1820BRead(int16_t param1_int, void(*Callback)(const char*)) {
	(void)Callback;

	char out[MAX_LOG_LINE_LENGTH];
	float tempC = 0.0;
	uint8_t result;
	result = InterfaceDS1820B_Read(&tempC, param1_int, 1);
	ITCHWrite(F("Result Code: "));
	Serial.println(result);
	FFFloatToCString(out, tempC);
	ITCHWrite(F("Temperature C: "));
	ITCHWriteLine(out);
}

void RegIFDS1820BTest(int16_t param1_int, void(*Callback)(const char*)) {
	(void)Callback;

	char out[MAX_LOG_LINE_LENGTH];
	float tempC = 0.0;
	uint8_t result = 0;
	uint16_t tries = 500;

	while ( (result != 1) && (tries > 0) ) {
		result = InterfaceDS1820B_Read(&tempC, param1_int, 0);
		Serial.print(result);
		tries --;
	}
	if (result == 1) {
		FFFloatToCString(out, tempC);
		ITCHWrite(F("Temperature C: "));
		ITCHWriteLine(out);
	}
}

void RegSetCommandOnBlockID(uint16_t id, uint16_t command, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80

	BlockNode *b;
	b = GetBlockByID(bll, id);
	char fmt_str[35];

	if (b == NULL) {
		strcpy_hal(fmt_str, F("Error: %d is not a valid block ID"));
		sprintf(out_str, fmt_str, id);
		Callback(out_str);
	} else {
		//XXX range check command
		strcpy_hal(fmt_str, F("Sending %d to Block ID: %d"));
		sprintf(out_str, fmt_str, command, id);
		Callback(out_str);
		switch(command) {
			case CMD_OUTPUT_ON:
				SetCommand(id, command);
				EventMsg(SSS, id, E_ADMIN, M_CMD_ACT);
				break;
			case CMD_OUTPUT_OFF:
				SetCommand(id, command);
				EventMsg(SSS, id, E_ADMIN, M_CMD_DEACT);
				break;
			default:
				EventMsg(SSS, id, E_ADMIN, M_ADMIN_CMD_NOT_SUPPORTED);
				break;
		}
	}
}

void RegShowTime(void(*Callback)(const char*)) {
	char hms_str[12];
	time_t now;
	char fmt_str[9];

	now = TimeNow();
	strcpy_hal(fmt_str, F("%H:%M:%S"));
	strftime(hms_str, 12, fmt_str, localtime(&now));
	Callback(hms_str);
}

void RegSetTime(const char* time_str, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	char tok_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	char *tok;
	uint8_t err = 1;
	uint8_t ton;

	strcpy(tok_str, time_str);
	tok = strtok(tok_str, ":");
	if (tok) ton = atoi(tok);
	if(tok && (ton < 24)) {
		tok = strtok(0, ":");
		if (tok) ton = atoi(tok);
		if(tok && (ton < 60)) {
			tok = strtok(0, ":");
			if (tok) ton = atoi(tok);
			if(tok && (ton < 60)) {
				err = 0;
				strcpy_hal(out_str, F("Time string is valid"));
				Callback(out_str);

#ifdef PLATFORM_LINUX
			    struct tm *tmptr;
			    time_t now;
			    time_t t;
				int rc;
				now = TimeNow();
				tmptr = localtime(&now);
			    strptime(time_str, "%H:%M:%S", tmptr);
			    t = mktime(tmptr);
			    rc = stime(&t);
			    if(rc==0) {
			        sprintf(out_str, "System stime() successful.");
			        Callback(out_str);
			    }
			    else {
			        sprintf(out_str, "Error: stime() failed, errno = %d: %s",errno, strerror(errno));
			        Callback(out_str);
			    }
#endif //PLATFORM_LINUX
#ifdef PLATFORM_ARDUINO
			    uint8_t rc = HALSetRTCTime(time_str);
			    if(rc==0) {
					strcpy_hal(out_str, F("HALSetRTCTime() successful"));
			        Callback(out_str);
			    }
			    else {
					strcpy_hal(out_str, F("Error: HALSetRTCTime() failed"));
			        Callback(out_str);
			    }
#endif //PLATFORM_ARDUINO

			}
		}
	}
	if (err) {
		strcpy_hal(out_str, F("Error: Time String not valid"));
		Callback(out_str);
	}

}

void RegShowDate(void(*Callback)(const char*)) {
	char ymd_str[14];
	time_t now;
	char fmt_str[9];

	now = TimeNow();
	strcpy_hal(fmt_str, F("%Y-%m-%d"));
	strftime(ymd_str, 14, fmt_str, localtime(&now));
	Callback(ymd_str);
}

void RegSetDate(const char* date_str, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	char tok_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	char *tok;
	uint8_t err = 1;
	uint16_t ton;

	strcpy(tok_str, date_str);
	tok = strtok(tok_str, "-");
	if (tok) ton = atol(tok_str);
	if(tok && (ton > 2000)) {
		tok = strtok(0, "-");
		if (tok) ton = atoi(tok);
		if(tok && (ton <= 12)) {
			tok = strtok(0, "-");
			if (tok) ton = atoi(tok);
			if(tok && (ton <= 31)) {
				err = 0;
				strcpy_hal(out_str, F("Date string is valid"));
				Callback(out_str);

#ifndef PLATFORM_ARDUINO
			    struct tm *tmptr;
			    time_t now;
			    time_t t;
				int rc;
				now = TimeNow();
				tmptr = localtime(&now);
			    strptime(date_str, "%Y-%m-%d", tmptr);
			    t = mktime(tmptr);
			    rc = stime(&t);
			    if(rc==0) {
					strcpy(out_str, "System stime() successful.");
			        Callback(out_str);
			    }
			    else {
			        sprintf(out_str, "Error: stime() failed, errno = %d: %s", errno, strerror(errno));
			        Callback(out_str);
			    }
#else
			    uint8_t rc = HALSetRTCDate(date_str);
			    if(rc==0) {
			    	strcpy_hal(out_str, F("HALSetRTCDate() successful"));
			        Callback(out_str);
			    }
			    else {
					strcpy_hal(out_str, F("Error: HALSetRTCDate() failed"));
			        Callback(out_str);
			    }
#endif //ifndef PLATFORM_ARDUINO

			}
		}
	}
	if (err) {
		strcpy_hal(out_str, F("Error: Date String not valid."));
		Callback(out_str);
	}

}

void RegConfigClear(void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80

	DropBlockList();
	strcpy_hal(out_str, F("Block List Reset"));
	Callback(out_str);

	DropInterfaceList();
	strcpy_hal(out_str, F("Interface List Reset"));
	Callback(out_str);
}

void RegConfigLoad(void(*Callback)(const char*)) {
	(void)Callback; 		//not used
	InitConfigLoad(1);
}

#ifdef RESURRECT_DEPRECIATED
void RegConfigLoadBinary(void(*Callback)(const char*)) {
	(void)Callback; 		//not used
	InitConfigLoadBinary();
}
#endif //RESURRECT_DEPRECIATED

/* 2019-06-14 Depreciated.
See Comments in init_config.cpp, function InitConfigLoadINI()
void RegConfigLoadINI(void(*Callback)(char*)) {
	(void)Callback; 		//not used
	InitConfigLoadINI();
}
*/

void RegConfigSave(void(*Callback)(const char*)) {
	(void)Callback; 		//not used
	InitConfigSave();
}

void RegConfigShow(void(*Callback)(const char*)) {
	(void)Callback; 		//not used
	InitConfigShow();
}

#ifdef RESURRECT_DEPRECIATED
void RegConfigSaveBinary(void(*Callback)(const char*)) {
	(void)Callback; 		//not used
	InitConfigSaveBinary();
}
#endif //RESURRECT_DEPRECIATED

void RegConfigInterface(const char* param1_string, uint16_t IF_CONFIG, const char* param2_string, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	char key[MAX_LABEL_LENGTH];

	strcpy_hal(key, if_config_keys[IF_CONFIG].text);
	if (ConfigureInterface(param1_string, key, param2_string) == 0) {
		GetMessageString(out_str, M_CONFIGURE_BLOCK_ERROR);
		Callback(out_str);
		strcpy_hal(out_str, F(" >>> CONFIG system "));
		strcat(out_str, param1_string);
		strcat_hal(out_str, F(" "));
		strcat(out_str, key);
		strcat_hal(out_str, F(" "));
		strcat(out_str, param2_string);
		Callback(out_str);
	}
}

void RegConfigBlockSystem(const char* param1_string, uint16_t SYS_CONFIG, const char* param2_string, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	char key[MAX_LABEL_LENGTH];

	strcpy_hal(key, sys_config_keys[SYS_CONFIG].text);
	if (ConfigureBlock(FF_SYSTEM, param1_string, key, param2_string) == 0) {
		GetMessageString(out_str, M_CONFIGURE_BLOCK_ERROR);
		Callback(out_str);
		strcpy_hal(out_str, F(" >>> CONFIG interface "));
		strcat(out_str, param1_string);
		strcat_hal(out_str, F(" "));
		strcat(out_str, key);
		strcat_hal(out_str, F(" "));
		strcat(out_str, param2_string);
		Callback(out_str);
	}
}

void RegConfigBlockInput(const char* param1_string, uint16_t IN_CONFIG, const char* param2_string, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	char key[MAX_LABEL_LENGTH];

	strcpy_hal(key, in_config_keys[IN_CONFIG].text);
	if (ConfigureBlock(FF_INPUT, param1_string, key, param2_string) == 0) {
		GetMessageString(out_str, M_CONFIGURE_BLOCK_ERROR);
		Callback(out_str);
		strcpy_hal(out_str, F(" >>> CONFIG input "));
		strcat(out_str, param1_string);
		strcat_hal(out_str, F(" "));
		strcat(out_str, key);
		strcat_hal(out_str, F(" "));
		strcat(out_str, param2_string);
		Callback(out_str);
	}
}

void RegConfigBlockMonitor(const char* param1_string, uint16_t MON_CONFIG, const char* param2_string, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	char key[MAX_LABEL_LENGTH];

	strcpy_hal(key, mon_config_keys[MON_CONFIG].text);
	if (ConfigureBlock(FF_MONITOR, param1_string, key, param2_string) == 0) {
		GetMessageString(out_str, M_CONFIGURE_BLOCK_ERROR);
		Callback(out_str);
		strcpy_hal(out_str, F(" >>> CONFIG monitor "));
		strcat(out_str, param1_string);
		strcat_hal(out_str, F(" "));
		strcat(out_str, key);
		strcat_hal(out_str, F(" "));
		strcat(out_str, param2_string);
		Callback(out_str);
	}
}

void RegConfigBlockSchedule(const char* param1_string, uint16_t SCH_CONFIG, const char* param2_string, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	char key[MAX_LABEL_LENGTH];

	strcpy_hal(key, sch_config_keys[SCH_CONFIG].text);
	if (ConfigureBlock(FF_SCHEDULE, param1_string, key, param2_string) == 0) {
		GetMessageString(out_str, M_CONFIGURE_BLOCK_ERROR);
		Callback(out_str);
		strcpy_hal(out_str, F(" >>> CONFIG schedule "));
		strcat(out_str, param1_string);
		strcat_hal(out_str, F(" "));
		strcat(out_str, key);
		strcat_hal(out_str, F(" "));
		strcat(out_str, param2_string);
		Callback(out_str);
	}
}

void RegConfigBlockRule(const char* param1_string, uint16_t RL_CONFIG, const char* param2_string, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	char key[MAX_LABEL_LENGTH];

	strcpy_hal(key, rl_config_keys[RL_CONFIG].text);
	if (ConfigureBlock(FF_RULE, param1_string, key, param2_string) == 0) {
		GetMessageString(out_str, M_CONFIGURE_BLOCK_ERROR);
		Callback(out_str);
		strcpy_hal(out_str, F(" >>> CONFIG rule "));
		strcat(out_str, param1_string);
		strcat_hal(out_str, F(" "));
		strcat(out_str, key);
		strcat_hal(out_str, F(" "));
		strcat(out_str, param2_string);
		Callback(out_str);
	}
}

void RegConfigBlockController(const char* param1_string, uint16_t CON_CONFIG, const char* param2_string, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	char key[MAX_LABEL_LENGTH];

	strcpy_hal(key, con_config_keys[CON_CONFIG].text);
	if (ConfigureBlock(FF_CONTROLLER, param1_string, key, param2_string) == 0) {
		GetMessageString(out_str, M_CONFIGURE_BLOCK_ERROR);
		Callback(out_str);
		strcpy_hal(out_str, F(" >>> CONFIG controller "));
		strcat(out_str, param1_string);
		strcat_hal(out_str, F(" "));
		strcat(out_str, key);
		strcat_hal(out_str, F(" "));
		strcat(out_str, param2_string);
		Callback(out_str);
	}
}

void RegConfigBlockOutput(const char* param1_string, uint16_t OUT_CONFIG, const char* param2_string, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];	// 80
	char key[MAX_LABEL_LENGTH];

	strcpy_hal(key, out_config_keys[OUT_CONFIG].text);
	if (ConfigureBlock(FF_OUTPUT, param1_string, key, param2_string) == 0) {
		GetMessageString(out_str, M_CONFIGURE_BLOCK_ERROR);
		Callback(out_str);
		strcpy_hal(out_str, F(" >>> CONFIG output "));
		strcat(out_str, param1_string);
		strcat_hal(out_str, F(" "));
		strcat(out_str, key);
		strcat_hal(out_str, F(" "));
		strcat(out_str, param2_string);
		Callback(out_str);
	}
}

void RegInitSetupAll(void(*Callback)(const char*)) {
	(void)Callback; 		//not used
	InterfaceDispatcher(SetupInterface);
	BlockDispatcher(Setup);
}

void RegInitSetupBID(uint16_t block_id, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];
	BlockNode *b;
	InterfaceNode *i;
	b = GetBlockByID(bll, block_id);
	if (b != NULL) {
		Setup(b);
	} else {
		i = GetInterfaceByID(ill, block_id);
		if (i != NULL) {
			SetupInterface(i);
		} else {
			strcpy_hal(out_str, F("Unknown Block ID"));
			Callback(out_str);
		}
	}
}

void RegInitValidateAll(void(*Callback)(const char*)) {
	(void)Callback; 		//not used
	InterfaceDispatcher(ValidateInterface);
	BlockDispatcher(Validate);
}

void RegInitValidateBID(uint16_t block_id, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];
	BlockNode *b;
	InterfaceNode *i;
	b = GetBlockByID(bll, block_id);
	if (b != NULL) {
		Validate(b);
	} else {
		i = GetInterfaceByID(ill, block_id);
		if (i != NULL) {
			ValidateInterface(i);
		} else {
			strcpy_hal(out_str, F("Unknown Block ID"));
			Callback(out_str);
		}
	}
}

void RegInitDisableAll(void(*Callback)(const char*)) {
	(void)Callback; 		//not used
	InterfaceDispatcher(InitDisableInterface);
	BlockDispatcher(InitDisable);
}

void RegInitDisableBID(uint16_t block_id, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];
	BlockNode *b;
	InterfaceNode *i;
	b = GetBlockByID(bll, block_id);
	if (b != NULL) {
		InitDisable(b);
	} else {
		i = GetInterfaceByID(ill, block_id);
		if (i != NULL) {
			InitDisableInterface(i);
		} else {
			strcpy_hal(out_str, F("Unknown Block ID"));
			Callback(out_str);
		}
	}
}

void RegAdminDisableBID(uint16_t block_id, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];
	BlockNode *b;
	InterfaceNode *i;
	b = GetBlockByID(bll, block_id);
	if (b != NULL) {
		b->status = STATUS_DISABLED_ADMIN;
	} else {
		i = GetInterfaceByID(ill, block_id);
		if (i != NULL) {
			b->status = STATUS_DISABLED_ADMIN;
		} else {
			strcpy_hal(out_str, F("Unknown Block ID"));
			Callback(out_str);
		}
	}
}

void RegAdminEnableBID(uint16_t block_id, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];
	BlockNode *b;
	InterfaceNode *i;
	b = GetBlockByID(bll, block_id);
	if (b != NULL) {
		b->status = STATUS_DISABLED_INIT;
	} else {
		i = GetInterfaceByID(ill, block_id);
		if (i != NULL) {
			b->status = STATUS_DISABLED_INIT;
		} else {
			strcpy_hal(out_str, F("Unknown Block ID"));
			Callback(out_str);
		}
	}
}

void RegConfigDeleteBID(uint16_t block_id, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];
	if (DeleteBlockByID(block_id) == 1) {
		strcpy_hal(out_str, F("Block / Interface Deleted"));
		Callback(out_str);
	} else {
		strcpy_hal(out_str, F("DeleteBlockByID Reported an Error"));
		Callback(out_str);
	}
}

void RegConfigDeleteBlockLabel(const char* BLOCK_LABEL, void(*Callback)(const char*)) {
	char out_str[MAX_MESSAGE_STRING_LENGTH];
	if (DeleteBlockByLabel(BLOCK_LABEL) == 1) {
		strcpy_hal(out_str, F("Block / Interface Deleted"));
		Callback(out_str);
	} else {
		strcpy_hal(out_str, F("DeleteBlockByLabel Reported an Error"));
		Callback(out_str);
	}
}

void RegSystemReboot(void(*Callback)(const char*)) {
	(void)Callback; 		//not used
	HALReboot();
}

void RegAdminCmdOnBID(uint16_t block_id, void(*Callback)(const char*)) {
	RegSetCommandOnBlockID(block_id, CMD_OUTPUT_ON, Callback);
}

void RegAdminCmdOffBID(uint16_t block_id, void(*Callback)(const char*)) {
	RegSetCommandOnBlockID(block_id, CMD_OUTPUT_OFF, Callback);
}

/********************************************************************************************
 * State Register and UI Data Set Functions
 ********************************************************************************************/

#ifdef ARDUINO_LCD
UIDataSet* GetUIDataSet(void) {
	return &sr.ui_data;
}
#endif //ARDUINO_LCD

void UpdateStateRegister(uint16_t source, uint8_t msg_type, uint8_t msg_str, int32_t i_val, float f_val) {

	(void)i_val;	// not used on the LCD

	//TODO include further registry block logic update here
	//TODO redo - remove hard coding perhaps **** INDEED
	//2019-06 Prob not needed for now - this was only used for the LCD display

#ifdef ARDUINO_LCD
	const char* src_label;
	src_label = GetBlockLabelString(source);

	//Update UI Data Fields with raw values and update MIN and MAX fields if they have changed
	if (src_label) {
		if (strcmp(src_label, DISPLAY_INSIDE_SOURCE_BLOCK) == 0) {
			sr.ui_data.inside_current = f_val;
			if (f_val < sr.ui_data.inside_min) {
				sr.ui_data.inside_min = f_val;
				sr.ui_data.inside_min_dt = TimeNow();
			}
			if (f_val > sr.ui_data.inside_max) {
				sr.ui_data.inside_max = f_val;
				sr.ui_data.inside_max_dt = TimeNow();
			}
		}

		if (strcmp(src_label, DISPLAY_OUTSIDE_SOURCE_BLOCK) == 0) {
			sr.ui_data.outside_current = f_val;
			if (f_val < sr.ui_data.outside_min) {
				sr.ui_data.outside_min = f_val;
				sr.ui_data.outside_min_dt = TimeNow();
			}
			if (f_val > sr.ui_data.outside_max) {
				sr.ui_data.outside_max = f_val;
				sr.ui_data.outside_max_dt = TimeNow();
			}
		}

		if (strcmp(src_label, DISPLAY_WATER_SOURCE_BLOCK) == 0) {
			sr.ui_data.water_current = f_val;
			if (f_val < sr.ui_data.water_min) {
				sr.ui_data.water_min = f_val;
				sr.ui_data.water_min_dt = TimeNow();
			}
			if (f_val > sr.ui_data.water_max) {
				sr.ui_data.water_max = f_val;
				sr.ui_data.water_max_dt = TimeNow();
			}
		}

	} else { //src_label Null
		DebugLog(SSS, E_ERROR, M_SR_BAD_ID);
	}

	if ( (msg_type == E_COMMAND) && (msg_str == CMD_RESET_MINMAX) ) {
		sr.ui_data.inside_min = sr.ui_data.inside_current;
		sr.ui_data.inside_min_dt = TimeNow();
		sr.ui_data.inside_max = sr.ui_data.inside_current;
		sr.ui_data.inside_max_dt = TimeNow();

		sr.ui_data.outside_min = sr.ui_data.outside_current;
		sr.ui_data.outside_min_dt = TimeNow();
		sr.ui_data.outside_max = sr.ui_data.outside_current;
		sr.ui_data.outside_max_dt = TimeNow();

		sr.ui_data.water_min = sr.ui_data.water_current;
		sr.ui_data.water_min_dt = TimeNow();
		sr.ui_data.water_max = sr.ui_data.water_current;
		sr.ui_data.water_max_dt = TimeNow();

		DebugLog(SSS, E_INFO, M_SR_MINMAX_RESET);
	}

	//TODO - decide: flags for lights and heater on UI?
	// Not used for now
	//sr.ui_data.light_flag = 0;
	//sr.ui_data.water_heater_flag = 0;
#else //!ARDUINO_LCD
	(void)source;
	(void)msg_type;
	(void)msg_str;
	(void)i_val;
	(void)f_val;
#endif //ARDUINO_LCD
}

void InitStateRegister(void) {
#ifdef ARDUINO_LCD
	DebugLog(SSS, E_INFO, M_INI_SR);

	sr.language = ENGLISH;
	sr.temperature_scale = CELSIUS;
	sr.time_real_status = 0; 	//false at this stage
	sr.FS_present = 0; 			//false at this stage
	sr.config_valid = 0;		//false at this stage
	sr.save_event_buffer = 0;

//initialise the min and max counters used for UI display
	sr.ui_data.inside_current = 0;
	sr.ui_data.inside_min = 100;
	sr.ui_data.inside_min_dt = TimeNow();
	sr.ui_data.inside_max = -50;
	sr.ui_data.inside_max_dt = TimeNow();

	sr.ui_data.outside_current = 0;
	sr.ui_data.outside_min = 100;
	sr.ui_data.outside_min_dt = TimeNow();
	sr.ui_data.outside_max = -50;
	sr.ui_data.outside_max_dt = TimeNow();

	sr.ui_data.water_current = 0;
	sr.ui_data.water_min = 100;
	sr.ui_data.water_min_dt = TimeNow();
	sr.ui_data.water_max = -50;
	sr.ui_data.water_max_dt = TimeNow();

	//TODO these will go
	//sr.ui_data.light_flag = 0;
	//sr.ui_data.water_heater_flag = 0;
#endif //ARDUINO_LCD
}

#ifdef PLATFORM_ARDUINO
char* GetMemPointers(char* str) {
/* This function places the current value of the heap and stack pointers in the
 * variables. You can call it from any place in your code and save the data for
 * outputting or displaying later. This allows you to check at different parts of
 * your program flow.
 * The stack pointer starts at the top of RAM and grows downwards. The heap pointer
 * starts just above the static variables etc. and grows upwards. SP should always
 * be larger than HP or you'll be in big trouble! The smaller the gap, the more
 * careful you need to be. Julian Gall 6-Feb-2009.
 */
	uint8_t * heapptr, * stackptr, *bll_tail;

	bll_tail = (uint8_t *)GetLastBlockAddr();
	stackptr = (uint8_t *)malloc(4);          // use stackptr temporarily
	heapptr = stackptr;                     // save value of heap pointer
	free(stackptr);      // free up the memory again (sets stackptr to 0)
	stackptr =  (uint8_t *)(SP);           // save value of stack pointer
	char fmt_str[33];
	strcpy_hal(fmt_str, F("ILL: %d  BLL: %d  SP: %d  HP: %d"));
	sprintf(str, fmt_str, (uint16_t)ill, (uint16_t)bll_tail, (uint16_t)stackptr, (uint16_t)heapptr);
	return str;
}
#endif //PLATFORM_ARDUINO

redpajama_set_name: RedPajamaGithub


text:
Hassasna (Aim Temuchente)
 Hassasna (Saida)
 Hassasna (distrito)

Desambiguações de topônimos

redpajama_set_name: RedPajamaWikipedia


Whenever roadway improvement projects are undertaken in residential communities, local property owners can be subject to eminent domain — the taking of some or all of the owner's property to accommodate the project. The Powell Road eminent domain project is no different.
The East Powell Road eminent domain construction project is designed to improve current and future mobility on East Powell Road. According to the Delaware County Engineer's office, there are several purposes and needs stated for this project.
Estimated vehicle traffic is expected to nearly double by 2035; exceeding the capacity of a two-lane road.
There are currently no pedestrian or bicycle facilities at the Powell Road eminent domain project.
The left turn crashes at the intersections are higher than statewide averages.
The curves and cross slopes on the existing roadway to not meet current design standards.
Provide sufficient roadway to accommodate future traffic.
Improve safety by designing new roadway to meet current design standards.
Furnish a bicycle and pedestrian path.
The proposed usage is illustrated in this architectural rendering.
Loss of use of some or all of their property.
Loss of value — "diminution of value" — of their property.
Increased foot, bicycle or vehicle traffic nearer to their property.
Clark Perdue has helped property owners with loss of property value and other losses resulting from various eminent domain projects. Power line installation and road constructions projects are just two of the many reasons why property owners are subject to the taking of some or all of their land. If we can help with a potential taking of land because of eminent domain, please call us.


Ceramic Thin Film Chip Inductor (AL Series) / Viking Tech has the experience in the design of innovative components, offering support and service to Global customers that demand a genuine manufacturing partner. Our goal is to be the leader in design, manufacturing, and marketing of miniature, precision passive components used throughout Automotive, Industrial and 3C electronic applications.
Viking's 0201 and 0402 series inductor is a photo lithographically etched single layer ceramic chip. Viking's design provides high SRF, excellent Q, and superior temperature stability. This highly stable inductor family is specifically designed for critical tolerance needs.
Photolithographic single layer ceramic chip.
High SRF, excellent Q, superior temperature stability.
Tight tolerance of ± 1% or ± 0.1nH.
Self resonant frequency controlled within 10%.
Stable inductance in high frequency circuit.
Highly stable design for critical needs.
Cellular Telephone, Pagers and GPS Products.
VCO, TCXO Circuit and RF Transceiver Module.
Wireless LAN, Bluetooth Module, Communication Appliances.
Based in Taiwan, Viking Tech Corporation is one of the prime Ceramic Thin Film Chip Inductor (AL Series) manufacturers since 1997. And their products are used throughout automotive, electronic device applications.


With 30 year's business experience, Electro Automation has gained a reputation for its world class customer service and product quality and is now a recognised leader in automation control within Europe.
The fully Irish-owned company was founded in 1984 in Dublin. Today the group has expanded to four companies, employing over 200 highly trained and motivated staff with branches in Dublin, Lisburn, Surrey and Germany.
Electro Automation supply, install and maintain a superb range of automatic gates and design tailor-made, safe and secure entrances to suit every budget.
Design versatility for automation is paramount, using hidden in-ground systems as well as electro-hydraulic rams and sliding gate operators. We can incorporate hydraulic and electronic locking systems and, if required, the gates can be integrated with an Access Control and/or CCTV System or other control method.
Automatic gates complete your security perimeter around both homes and commercial premises, and can be a significant deterrent to the opportunist burglar, car thief or vandal.
Automatic Bollards provided by Electro Automation provide a high degree of security in a discreet and aesthetically pleasing manner. Automatic bollards can be linked to access control systems or used by themselves to provide security to a site perimeter without unsightly fencing. They come in a wide range of colours and styles.
Electro Automation has many versions of turnstiles manufactured for addressing the challenges of access and security control for the entrances of airports, sports facilities, libraries and other facilities requiring managed pedestrian traffic flow.
They allow a flexible approach to providing effective access control in areas where previously security had been desirable but the associated aesthetic implications had been unwelcome or prohibitive. Their transparent and elegant design blends seamlessly into any type of architecture.
Electro Automation offers a range of pedestrian and vehicular access control systems that can be integrated with other products using swipe cards, pin codes, proximity readers, biometric readers, radio frequency and number plate recognition.


text: Q: Conda py2 environment uses pip3 instead of pip I've downloaded Miniconda3 and I've activated the Python2.7 environment. I've looked in the bin directory and it contains pip. I've tried to pip install numpy, but it redirects to /usr/local/bin/pip3 and I get the error that the pip package is not found. Why is it prioritizing Python 3.8? The only thing I can think of is changing my $PATH variable to only include /miniconda3/envs/py2/bin. I'd appreciate any suggestions - thanks!