text:
Südtiroler Informatik AG.
Empowering content creators across 30 school websites.
SIAG, the in-house IT services provider for multiple public administration organizations in South Tyrol, transitioned dozens of schools to a reusable Kontent.ai project.
www.siag.it
Each school site used different, outdated codebases
Content was secondary to design
Technical experts were needed to manage the sites
SIAG analyzed the content needs of schools
A reusable Kontent.ai project was created and copied for each school
Site editors switched to a content-first strategy
Streamlined content process puts content experts, not IT staff, in control.
Enabling content creators creates more value for students and teachers.
Content is published much faster than before.
Südtiroler Informatik AG (SIAG) is an in-house company that provides IT services for the South Tyrolean Provincial Administration, the South Tyrolean Association of Municipalities, and the Trentino-South Tyrol region. They play a key role in the digitalization of public administration in the northernmost Italian province.
As part of their duties, SIAG is responsible for administrating the web presence for 30 vocational schools in South Tyrol. These sites are a crucial source of information for current and prospective students, so it's important for their content to be relevant, up to date, and easy to maintain.
That's why, when it was time to modernize these sites, SIAG chose Kontent.ai as their modular content platform. The choice would help put the contents of the site in the hands of content experts, creating value for both students and teachers. And a modern tech architecture, supported by Kontent.ai, would also significantly improve their development process.
SIAG was faced with the challenge of renovating 30 websites that had all been built separately. Each site had its own codebase, its own style and quirks, and its own way of adding new content. This created inconsistency across the sites' content and meant that technical experts were required to add new content. Subject matter experts couldn't add or edit site content on their own. "The content was not clearly defined…Some schools were using web art to publish a news article on their site, another school was using a different type of content block," said Stefan Zuegg, Senior Web Developer at SIAG.
An additional challenge was the technology the sites were using. When the sites were originally developed more than 12 years ago, they used some of the most modern technologies available. But as time passed, the technology became outdated. The original design of the sites didn't anticipate the rise of mobile browsing and didn't take advantage of the features offered by modern web technologies.
SIAG knew that improved sites could create more value for both the schools and their students. They decided to go for a fresh start, with a content-first approach.
To kick off the project, they started by analyzing how each school was using their site. They discovered that despite discrepancies in how they chose to display their content, the schools all had similar requirements for the type of content they were publishing.
Kontent.ai provided a clear opportunity here: they could create a single Kontent.ai project, which could be reused across all their schools. SIAG used their research on the type of content the schools were publishing to define clear content types that all the schools could utilize for their publishing needs.
The new content types were focused on simplicity. They didn't offer hundreds of options for formatting or displaying the text. This helped ensure that content creators focused on the content, instead of spending time worrying about the layout. Stefan Zuegg, SIAG's Senior Web Developer noted: "With Kontent.ai, it was no longer necessary for the school technician or IT teacher to have access to the CMS and to write the content. We wanted the content experts to access the CMS: people that could write good texts, people that are creative. This was a very important shift."
SIAG also simultaneously built a new shared codebase for all the schools' sites. The new development architecture relied on cloud-based tools, including Kontent.ai, and used an automated deployment pipeline to make maintenance as simple as possible. Now, if a modification is made to the codebase, it's automatically rolled out to all the schools' sites.
After the project was rolled out, SIAG received lots of great feedback from the sites' content creators. Users were publishing more content at a faster pace than before. And more importantly, subject matter experts were able to publish the content themselves.
A surprising reaction was how happy end-users were with the simplification of the content creation process. Users had fewer options for how to display their content, but they appreciated the simplicity since it allowed them to focus on what they were writing.
Ultimately, the new project enabled the schools to create more value from the content they produce, in less time and with less hassle.
Stefan Zuegg describes the impact of Kontent at SIAG
Watch the full talk from SIAG, "Creating a reusable Kontent.ai project to power 30 different school websites," from the 2021 Kontent.ai Horizons conference.
Transitioning 30 school websites
to a single, simplified codebase
Empowering content creators
with a user-friendly Kontent.ai project
Increasing content output and quality
through a simplified process
"It's almost liberating for our content creators to be able to concentrate on the essentials. Using Kontent.ai's modular content platform, they can concentrate on what matters most: creating good content. When they realized they could publish information much faster – and even easier – with the new system, they also ended up producing more content."
Stefan Zuegg, Senior Web Developer, SIAG
See how Kontent.ai can support your business
Learn why customers worldwide love using Kontent.ai.
Schedule a free 1-on-1 demo for a personal walkthrough of all the benefits of the platform to see how you can empower your teams and delight your customers. You'll learn how to:
Reach your audience on any channel or device
Streamline content operations to publish better content faster
Design a best-of-breed microservices architecture to deliver engaging experiences
After filling out the form, our Sales team will contact you to schedule a time that best fits your needs. Want to learn more about our modular content platform first? Contact us.
Try Kontent.ai free for 30-days
Try Kontent.ai
Select from the list
I agree with using my details for Kontent.ai marketing and sales communications.
You may withdraw your consent at any time and manage your data in Consent Settings. You can read our privacy notice here.


text:
Fast and robust identification of railway track stiffness from simple field measurement
C. Shen, R.P.B.J. Dollevoet, Z. Li
We propose to combine a physics-based finite element (FE) track model and a data-driven Gaussian process regression (GPR) model to directly infer railpad and ballast stiffness from measured frequency response functions (FRF) by field hammer tests. Conventionally, only the rail resonance and full track resonance are used as the FRF features to identify track stiffness. In this paper, eleven features, including sleeper resonances, from a single FRF curve are selected as the predictors of the GPR. To deal with incomplete measurements and uncertainties in the FRF features, we train multiple candidate GPR models with different features, kernels and training sets. Predictions by the candidate models are fused using a weighted Product of Experts method that automatically filters out unreliable predictions. We compare the performance of the proposed method with a model updating method using the particle swam optimization (PSO) on two synthesis datasets in a wide range of scenarios. The results show that the enriched features and the proposed fusion strategy can effectively reduce prediction errors. In the worst-case scenario with only three features and 5% injected noise, the average prediction errors for the railpad and ballast stiffness are approximately 12% and 6%, outperforming the PSO by about 6% and 3%, respectively. Moreover, the method enables fast predictions for large datasets. The predictions for 400 samples takes only approximately 10 s compared with 40 min using the PSO. Finally, a field application example shows that the proposed method is capable of extracting the stiffness values using a simple setup, i.e., with only one accelerometer and one impact location.
Mechanical Systems and Signal Processing
https://doi.org/10.1016/j.ymssp.2020.107431
Field hammer test
Frequency response function
Gaussian process regression
Railway track stiffness
Structural identification
10.1016/j.ymssp.2020.107431
1-s2.0-S0888327020308177-mainFinal published version, 4.93 MBLicence: CC BY
Dive into the research topics of 'Fast and robust identification of railway track stiffness from simple field measurement'. Together they form a unique fingerprint.
Stiffness Engineering & Materials Science 100%
Frequency response Engineering & Materials Science 86%
Hammers Engineering & Materials Science 28%
Large dataset Engineering & Materials Science 26%
Accelerometers Engineering & Materials Science 22%
Physics Engineering & Materials Science 20%
Rails Engineering & Materials Science 20%
Fusion reactions Engineering & Materials Science 19%
Shen, C., Dollevoet, R. P. B. J., & Li, Z. (2021). Fast and robust identification of railway track stiffness from simple field measurement. Mechanical Systems and Signal Processing, 152, 1-25. [107431]. https://doi.org/10.1016/j.ymssp.2020.107431
Shen, C. ; Dollevoet, R.P.B.J. ; Li, Z. / Fast and robust identification of railway track stiffness from simple field measurement. In: Mechanical Systems and Signal Processing. 2021 ; Vol. 152. pp. 1-25.
@article{5caeb971bd4a4746897bc327e5974f9c,
title = "Fast and robust identification of railway track stiffness from simple field measurement",
abstract = "We propose to combine a physics-based finite element (FE) track model and a data-driven Gaussian process regression (GPR) model to directly infer railpad and ballast stiffness from measured frequency response functions (FRF) by field hammer tests. Conventionally, only the rail resonance and full track resonance are used as the FRF features to identify track stiffness. In this paper, eleven features, including sleeper resonances, from a single FRF curve are selected as the predictors of the GPR. To deal with incomplete measurements and uncertainties in the FRF features, we train multiple candidate GPR models with different features, kernels and training sets. Predictions by the candidate models are fused using a weighted Product of Experts method that automatically filters out unreliable predictions. We compare the performance of the proposed method with a model updating method using the particle swam optimization (PSO) on two synthesis datasets in a wide range of scenarios. The results show that the enriched features and the proposed fusion strategy can effectively reduce prediction errors. In the worst-case scenario with only three features and 5% injected noise, the average prediction errors for the railpad and ballast stiffness are approximately 12% and 6%, outperforming the PSO by about 6% and 3%, respectively. Moreover, the method enables fast predictions for large datasets. The predictions for 400 samples takes only approximately 10 s compared with 40 min using the PSO. Finally, a field application example shows that the proposed method is capable of extracting the stiffness values using a simple setup, i.e., with only one accelerometer and one impact location.",
keywords = "Field hammer test, Frequency response function, Gaussian process regression, Railway track stiffness, Structural identification",
author = "C. Shen and R.P.B.J. Dollevoet and Z. Li",
doi = "10.1016/j.ymssp.2020.107431",
journal = "Mechanical Systems and Signal Processing",
publisher = "Academic Press",
Shen, C, Dollevoet, RPBJ & Li, Z 2021, 'Fast and robust identification of railway track stiffness from simple field measurement', Mechanical Systems and Signal Processing, vol. 152, 107431, pp. 1-25. https://doi.org/10.1016/j.ymssp.2020.107431
Fast and robust identification of railway track stiffness from simple field measurement. / Shen, C.; Dollevoet, R.P.B.J.; Li, Z.
In: Mechanical Systems and Signal Processing, Vol. 152, 107431, 2021, p. 1-25.
T1 - Fast and robust identification of railway track stiffness from simple field measurement
AU - Shen, C.
AU - Dollevoet, R.P.B.J.
N2 - We propose to combine a physics-based finite element (FE) track model and a data-driven Gaussian process regression (GPR) model to directly infer railpad and ballast stiffness from measured frequency response functions (FRF) by field hammer tests. Conventionally, only the rail resonance and full track resonance are used as the FRF features to identify track stiffness. In this paper, eleven features, including sleeper resonances, from a single FRF curve are selected as the predictors of the GPR. To deal with incomplete measurements and uncertainties in the FRF features, we train multiple candidate GPR models with different features, kernels and training sets. Predictions by the candidate models are fused using a weighted Product of Experts method that automatically filters out unreliable predictions. We compare the performance of the proposed method with a model updating method using the particle swam optimization (PSO) on two synthesis datasets in a wide range of scenarios. The results show that the enriched features and the proposed fusion strategy can effectively reduce prediction errors. In the worst-case scenario with only three features and 5% injected noise, the average prediction errors for the railpad and ballast stiffness are approximately 12% and 6%, outperforming the PSO by about 6% and 3%, respectively. Moreover, the method enables fast predictions for large datasets. The predictions for 400 samples takes only approximately 10 s compared with 40 min using the PSO. Finally, a field application example shows that the proposed method is capable of extracting the stiffness values using a simple setup, i.e., with only one accelerometer and one impact location.
AB - We propose to combine a physics-based finite element (FE) track model and a data-driven Gaussian process regression (GPR) model to directly infer railpad and ballast stiffness from measured frequency response functions (FRF) by field hammer tests. Conventionally, only the rail resonance and full track resonance are used as the FRF features to identify track stiffness. In this paper, eleven features, including sleeper resonances, from a single FRF curve are selected as the predictors of the GPR. To deal with incomplete measurements and uncertainties in the FRF features, we train multiple candidate GPR models with different features, kernels and training sets. Predictions by the candidate models are fused using a weighted Product of Experts method that automatically filters out unreliable predictions. We compare the performance of the proposed method with a model updating method using the particle swam optimization (PSO) on two synthesis datasets in a wide range of scenarios. The results show that the enriched features and the proposed fusion strategy can effectively reduce prediction errors. In the worst-case scenario with only three features and 5% injected noise, the average prediction errors for the railpad and ballast stiffness are approximately 12% and 6%, outperforming the PSO by about 6% and 3%, respectively. Moreover, the method enables fast predictions for large datasets. The predictions for 400 samples takes only approximately 10 s compared with 40 min using the PSO. Finally, a field application example shows that the proposed method is capable of extracting the stiffness values using a simple setup, i.e., with only one accelerometer and one impact location.
KW - Field hammer test
KW - Frequency response function
KW - Gaussian process regression
KW - Railway track stiffness
KW - Structural identification
U2 - 10.1016/j.ymssp.2020.107431
DO - 10.1016/j.ymssp.2020.107431
JO - Mechanical Systems and Signal Processing
JF - Mechanical Systems and Signal Processing
Shen C, Dollevoet RPBJ, Li Z. Fast and robust identification of railway track stiffness from simple field measurement. Mechanical Systems and Signal Processing. 2021;152:1-25. 107431. https://doi.org/10.1016/j.ymssp.2020.107431

redpajama_set_name: RedPajamaCommonCrawl


text:
Moraes determines Valdemar Costa Neto's testimony to the PF for declaration on proposed coup decree
Top 5 Plumbing companies in NYC
Waste: waste-to-energy plant and differentiated, plan for clean Rome
(ANSA) – ROME, AUGUST 04 – Garbage that remains on the street, full bins, dirty streets: in the capital garbage is now a chronic emergency but the crisis could come to an end, even if the point of "excellence" it won't be right at your fingertips. A waste-to-energy plant and four other plants with the ambition of reaching "zero landfill": this is Roberto Gualtieri's plan for clean Rome. The mayor, and extraordinary government commissioner, illustrated figures, numbers and objectives to give the city the dignity it deserves, currently inefficient even on the differentiated front "at 45.2%, a figure much lower than the national average of 61, 3% ".
Meanwhile, a road map with a precise time schedule. "As an extraordinary commissioner, I will issue an ordinance that will take the Waste Plan as a basis, and with this, no later than August 12, I will start the strategic environmental assessment", said Gualtieri. The final plan will then be approved with the order of the extraordinary commissioner on 15 October. At the same time, "the tender procedures will be published, for the expressions of interest of those who want to apply to build the plants". Rome will see an 8.3% reduction in waste "around 2030" (ANSA).
Roberto-Gualtieri
Special Commissioner
waste-floor
Ambushed in Alatri, Thomas Bricca in an irreversible coma
Should I pick up my son at "parents' time"?
Why Darmanin messes up political vocabulary
The minister and the hospitals: Lauterbach's reform is necessary – but something is missing from the plan
Wrong time: Scholz made the right decision with his no to fighter jets
'Via Delmastro and Donzelli'. But Salvini locks them down: 'It's not in question'
PETR4, VALE3 and other BB Investimentos shares to profit in the month
Nubank (NU) or Inter (INTR)? Only one will make a profit in 4Q22; see what to expect from banks
Vale (VALE3): Iron ore production reaches 80.8 million tons in 4Q22
It is possible that Americanas controllers got 'enjoyed' in the case, says Minister of Labor


text:
Edinburgh software company founder wins CEO title at Scottish technology awards
Benny Higgins: Perplexing times are always accompanied by challenges and plentiful opportunities
Edinburgh tech start-up Trickle secures seed funding deal
Scottish entrepreneur Paul Reid has secured backing from angel investors and venture capital outfit Techstart Ventures as he looks to grow his latest start-up, Trickle.
By Scott Reid
2nd Dec 2019, 8:18am
Ross Dempster, Paul Reid, Ed Henderson and Marcella Peacock of Trickle. Picture: Nick Mailer
Founded in Edinburgh in 2018, Trickle aims to drive improved employee engagement among large corporates and small and medium-sized enterprises (SMEs).
The venture launched into the UK market earlier this year and is already winning business across the commercial and public sectors, with recent client wins and assignments including ScottishPower, the Scottish Government and Disclosure Scotland.
Reid previously founded Edinburgh-based digital mapping outfit Sigma Seven, which was acquired by FTSE 100 outsourcing giant Capita in 2015. He has brought in some of the Sigma Seven team to his new venture, including fellow co-founder Ross Dempster, who is Trickle's chief technology officer.
A number of angel investors who had previously backed Sigma Seven, along with Techstart Ventures, have supported Trickle with seed funding of almost £1 million.
Reid, who is Trickle's chief executive, said: "When Sigma Seven was acquired by one of the UK's largest companies, I saw first-hand how corporate culture can impact people and I was always thinking about how I had to feed or trickle my team's sentiments back to the new management.
"With Trickle, we've built a people-first technology platform so that a conduit exists to channel employee issues and suggestions to senior management and HR. The end result is a virtuous circle that helps people feel more valued within the organisations we're partnering with."
The company's technology platform features an "analytics dashboard" which highlights the top-five issues or suggestions from employees, called "trickles", enabling a company's senior management team and HR function to know where to focus their attention.
Fast-growing
While the venture is working alongside large national and international companies, some of whom are going through or have gone through restructuring or transformational change, the SME market is also proving to be a fast-growing segment for the team.
Trickle's chief operating officer, Marcella Peacock, said: "Studies show that a happily employed person is more than twice as productive as a satisfied one and more than three times as productive as a dissatisfied person at work.
"Today's start-ups are thinking more about culture than ever before from day one. For the more established organisations, they realise that in today's corporate world, putting real focus on engaging your workforce results in higher productivity, increased loyalty and reduced staff churn."
Trickle, which was one of the companies that joined the third cohort of the Scottish Government's CivTech digital accelerator programme in 2018, plans to grow its headcount from six to ten. At the end of October, the firm also won CivTech's fourth cohort to work alongside West Dunbartonshire Council on its people engagement.
Sigma Seven was acquired by Capita for an undisclosed sum, and became part of the Footsie giant's digital and software solutions unit.
Capita seeks small firm link-ups


President Donald Trump on Thursday authorized the Pentagon to carry out a more robust air campaign against al-Shabaab in Somalia.
"The President has approved a Department of Defense proposal to provide additional precision fires in support of African Union Mission in Somalia," the Pentagon said in a statement.
Spokesman Capt. Jeff Davis said the additional powers "will help deny al-Shabaab safe havens from which it could attack U.S. citizens or U.S. interests in the region."
Specifically, the new authorities will help the U.S.'s local partners "increase pressure on al-Shabaab" while reducing threats to those forces, the Pentagon said.
Al-Shabaab is a militant Salafist group linked to al-Qaeda. In 2012, the group's former leader, Mukhtar Abu al-Zubair, said the east African terror group pledged fealty to al-Qaeda, an announcement welcomed by al-Qaeda chief Ayman al-Zawahiri.
Al-Zubair was killed in a U.S. drone strike in 2014.
His fighters have carried out a number of attacks inside Somalia in a bid to topple the internationally-recognized federal government, as well as extraterritorial attacks, particularly in Kenya.
In January dozens of Kenyan troops were killed in an al-Shabaab raid on a Kenyan military base. The group's militants carried out an attack at a university that slaughtered nearly 150 victims in 2015, and an attack on a mall in 2013 killed more than 60 people.
Al-Shabaab Donald Trump Somalia U.S.


Second entry for Plan B in what has been another stand-out year for the multi-talented artist. After the success of "Strickland Banks", it would have been easy for Ben Drew to fall into the comfort zone of producing another soul record, but he ripped up the formula and wrote and produced not only a critically-acclaimed film, but also a top class album by the same name. Writing in The Independent, Tim Walker called this title track "an all-time great protest song" & one MP compared it to Marvin Gaye's classic, "What's Going On". This guy will be around for the long-term.
This entry was posted in Colm G Charts and tagged Colm G, entertainment, Living Legend Colm G, music, Top 40 of 2012, video, X Charts. Bookmark the permalink.


On the road in FL.
Got off at the next exit.
Actually verbalized "Eek!" like a startled mouse when I saw the Sanford sign with the arrow pointing left.
Made a legal U-turn to get back on the highway.
Panicked when I saw the police car behind me.
Not wanting to drive into Sanford? You know why.
Police panic? The last time I got pulled over by a cop was at Broward College Davie Campus. He was abrasive so I handled it the only way I could without bursting into tears – expressionless, brief answers. My license was suspended. He wanted to know why I was on the campus and didn't believe me when I said I taught there. "You don't look like a professor." He had me out of the car with my hands on the trunk and was arresting me when an older Hispanic cop showed up. This one talked to me like I was a person so I started crying. He convinced the Nazi to let me go.


As we have previously written, on 29 April 2015 the European Parliament and the Council adopted the Interchange Fee Regulation (IFR). Whilst the IFR's provisions take effect on different dates, arguably the biggest change, the interchange fee cap, came into effect on 9 December 2015.
Interchange fees are paid from the merchant acquirer (the merchant's bank) to the card issuer (the cardholder's bank), as a percentage of each transaction made by the card-holder. These fees are set by the card scheme, such as Visa or MasterCard.
From 9 December 2015, the interchange fees cannot exceed 0.2% for debit cards and 0.3% for credit cards, which the British Retail Consortium estimates will save UK merchants an estimated £480 million every year.
The IFR cap must also be read in conjunction with the second Payment Services Directive which, when transposed into national law, will prohibit surcharging for the use of payment instruments which are subject to the caps. The cost savings from the fee caps should therefore be passed on to merchants and consumers.
The provisions relating to business rules mostly come into force on 9 June 2016.
Who will enforce the IFR in the UK?
Under the IFR, all EU Member States must designate a competent authority to supervise the IFR and which is granted the necessary investigatory and enforcement powers to do so. HM Treasury confirmed on 17 November 2015 that this would be the Payment Systems Regulator (PSR) in the UK.
The UK government has also assigned a role to the Financial Conduct Authority where certain provisions of the IFR overlap with its existing remit, such as under the UK Payment Services Regulations 2009.
Scope of IFR: what's in and what's out?
The IFR imposes obligations on payment card schemes, issuing and acquiring payment service providers (PSPs), processing entities, other technical service providers and, in limited circumstances, merchants. There are some notable exceptions. In particular, the IFR does not apply to transactions with commercial cards or cash withdrawals at ATMs. Also, while the IFR cap applies to four-party schemes (such as Visa and MasterCard), transactions with payment cards issued by three-party schemes (where there is a joint issuer and acquirer) are not caught.
However, when a three party payment card scheme licenses other PSPs for the issuance of card-based payment instruments or the acquiring of card-based payment transactions, or both, or issues card-based payment instruments with a co-branding partner or through an agent, it is considered to be a four party payment card scheme and will be caught by the IFR cap, as is the case for Amex.
That said, we understand that, in the UK, HM Treasury is granting an exemption from the interchange fees for certain three party schemes. Until 9 December 2018, three party schemes caught by the IFR (as explained above) will be exempt from the domestic interchange fee cap if they are within the market share safe harbour; namely, if the value of their annual UK card-based payment transactions is no more than 3% of all UK domestic card-based payment transactions. However, this de minimis exemption is time limited and only applies to transactions in which the issuer, merchant and acquirer are all in the UK.
penalties which can be imposed for breach.
The draft PSR guidance states that the PSR will monitor compliance with the interchange fee caps by requiring schemes and issuing and acquiring PSPs to provide evidence to the PSR under the IFR information-gathering powers. In particular, the PSR will gather initial compliance reports and seek data to demonstrate compliance with the caps.
The PSR will also consider complaints received in relation to compliance with the IFR, and act on them as appropriate.
seek an injunction to bring the compliance failure to an end, remedy the non-compliance or restrain dealing with assets.
Certain decisions by the PSR are appealable to the UK's specific competition tribunal: the Competition Appeal Tribunal.
The first consultation closes on 29 January 2016, with the PSR publishing its final approach in Spring 2016. The consultation notes that the PSR "will require certain stakeholders to submit data and information to the PSR as part of its approach to monitoring compliance with the IFR" and that the first requests will be sent shortly after 9 December 2015.
The PSR announced that its second consultation, on the remaining IFR provisions which come into force on 9 June 2016, will be issued in 2016.


It is pointless to underestimate the efforts involved in the mobile app development process since they are in abundance and have the potential to spin the IOS App market if there is the accurate dosage of app functionalities integrated into the mobile app development process. Who doesn't want to gain the maximum reviews on a mobile app, which helps the mobile app and the businesses to boom at the same time.
I have got to see many app developers who have a fantastic mobile app concept and a well-trained team to deliver the results, yet mobile app fails to get commendable reviews. This generally occurs when some mandatory points are avoided during and after the app-launch. I personally consider some essential Don'ts to be considered as a part of the app development process to set the success milestone for your mobile app, so read it ahead to know the secret ingredients to attain 1 million reviews for your mobile app.
Hmm, this is the interesting part, which completes your mobile app. An app video or most commonly called as app preview video. This is the feature which can break and make your app success chances to a large, so don't create any random app video, rather pick some references of mobile apps from the App Store and your app preview video which beautifully translates your app features. Invest time here, don't rush, since the final output needs to speak to the creative side of your iOS app.
When it comes to market your app to lure more downloads and reviews, then screenshots and app description, do not match the wavelength of any other marketing gimmick. The app screenshots cannot be ANY from the mobile app, but needs to be carefully picked, which speak the functionality of your app, app design and some unique feature, my tip here goes, that DO NOT pick the easy screens from your mobile app, but the complex one only. On the other hand, the App Description is the synopsis of your mobile app, make it succinct, crisp and unique, so your app users can understand what your app delivers through the app description. Add keywords within the app description to gain adequate visibility on your user's search results.
This point proves further, that why marketing needs detailed research and analysis when a mobile app is developed, it is developed with a thorough research on the targeted audience, market demands, challenges related to marketing and demographic, which all in return gives a stable platform for app marketing. In this run, you need to understand when you are planning to release your mobile app because the time you pick to release your mobile affects mobile app visibility. For instance, research and analyze the targeted market's holiday calendar, and if your iOS mobile app is not matching the taste of holiday spirit, then no need to release your app in the holiday season, since the app market swells up with the competition during the holiday season and you would get fewer visibility chances.
The Apple store is a little more particular with their guidelines being compared to any other OS. So if your app has some specific requirements like working only with the internet, and has no offline connectivity feature, then you need to inform your users about this limitation, through any pop-up message or any other notification message which would clarify your users that 'You are offline', this would create a loyalty factor for your mobile app users, and they would not get confused by thinking that mobile app is not functioning properly.
No, I am not aiming to scare you, but your iOS mobile app is a dream concept for its business domain and it needs to be well-developed and given attention closely while picking up the marketing strategy to work along with it, which only makes it possible for your iOS mobile app to gain visibility in the App Store and get satisfactory REVIEWS in number ,failing to which your mobile app would be lost in the heap of dust. I know there are more DONT'S to be considered to get an impressive app download rate and reviews, but I really hope the above-mentioned would also help you to get your efforts acknowledged by the AppStores.
To wrap up, I would suggest, that always remember that conduct a full-fledged market research to know why users will need you app and how and where and when they will use it, will increase your chances of developing a mobile app development which would give right fruit, because the harsh fact says, if your users don't connect with your app; it turns out to be a failure.
So till next time…Happy Reading to all the lovely people out there…Keep enjoying and keep developing successful mobile apps.


Product and marketing teams collect a lot of data. And you need a way to highlight and share the insights you glean from all that data. That is why we include powerful analytics capabilities in Aha! — so you can analyze all of your data and share it with the team. To make this process go even faster, we just added new formatting options to help you make the reports look exactly like you want them to.
You can now quickly add new data, sort and filter, and adjust column widths on Aha! list reports.
Previously, filtering a list report required opening a modal and making several clicks. Now, there is a new menu that appears when you hover over each column heading. This menu includes options for sorting, adding and filtering data, and deleting the column.
Let's say you want to show the status of planned product features or marketing activities. In the example below, we use the default set of columns and filters that appear when the list report is created. Now you can sort or apply additional filters right there. Or add an entirely new data column like you see here.
The More options button only appears when you hover over the heading of each column.
The example below shows how you can click the border of any column and adjust the width — allowing you to give viewers a better reading experience. But this enhancement is not just for list reports. You can now adjust column widths on pivot reports too.
Customized column widths are preserved when you save the report, add the view to an Aha! notebook, or export it to a PDF.
We hope this update makes it easier for you to format your reports — your way.
So go get started. Create new list and pivot reports and organize the details. And let us know what other actions would be helpful in this dropdown — we want to hear your ideas.
List reports and the enhanced formatting options are available to all Aha! customers. If you are not already an Aha! customer, you may want to sign up for a free 30-day trial or join a live demo to see why more than 250,000 users trust Aha! to set brilliant strategy, capture customer ideas, create visual roadmaps, and manage breakthrough marketing programs.
Bryan loves helping product and marketing managers successfully build and launch products that they are proud of. He is a Sr. Product Marketing Manager at Aha! — the world's #1 product roadmap and marketing planning software. Previously, he established the product management discipline at Banno (a fintech startup acquired by Jack Henry & Associates) before moving over to lead the company's product marketing.


text:
Q: Why is this double type variable default to int when passed as a function parameter? I am learning C and was trying to help debug a friends code.
He was defining his function parameters in the global scope and then passing them into the function def like so:
#include <stdio.h>

double x;

double myfunc(x){
    return x;
}

void main(){

}

I get this is wrong, but not why the following error comes up:
main.c:14:8: warning: type of 'x' defaults to 'int' [-Wimplicit-int]

Can someone help me understand how the computer is interpreting this code?

A:
He was defining his function parameters in the global scope

No, he does not.
The global x is unrelated to the function's parameter x.
The former is a global double, the latter is local to the function and, as the compiler is warning, "defaults to int".

I get this is wrong

It is not wrong, but not possible.

A: The global variable
double x;

has no relation to the parameter x of func.
Since the type of x isn't provided, compiler defaults to int type (pre-C99). But this assumption isn't valid since C99.
So either specify the type for x (such as: double func(double x) { ...}) or simply don't pass any argument to it at all if you want to use the global x.
As a general rule, avoid globals. Or at least make it static so that it's not visible outside the translation unit.

A: Your friend is using an older, K&R-style of function definition, where parameter types are specified separately from the parameter list.  If done correctly, it would look like this:
double myfunc(x)
  double x;
{
  return x;
}

However, it's better to use prototype syntax, where the parameter type is specified with the parameter name:
double myfunc( double x )
{
  return x;
}

Note that this parameter x has nothing to do with the global variable x - it is an entirely separate object.
Under older versions of C, if a function had no return type, or if a parameter wasn't declared with a type, the compiler assumed it had type int.  Implicit int typing was done away with in the 1999 standard IINM, and shouldn't be relied upon.

A: When you write:
double myfunc(x){
    return x;
}

you are declaring a function in the legacy style of the first edition of Kernighan & Ritchies book "The C Programming Language".
That style, still alive, allows you to declare a function just naming its parameters (which are always local to the function, so the global x is a different variable than the parameter x to the function)  and, as you don't specify its type, it defaults to int.  So you are actually declaring (in ANSI-C) the following function:
double myfunc(int x){
    return x;
}

and, as you see, it takes an integer parameter.
Parameters to a function are ALWAYS local to the function, you cannot make them global variables.
Note:
If you want to define the function in old style C, the proper definition would be:
double myfunc(x)
    double x;
{
    return x;
}

in ANSI-C is:
double myfunc(double x)
{
    return x;
}

I tried to compile the next program in my computer:
#include <math.h>
#include <stdio.h>

double myFunc(x)
{
        return x;
}

int main()
{
        printf("%g\n", myFunc(M_PI));
}

with the following WARNING:
$ make pru
cc -O2 -pipe  pru33336.c  -o pru33336
pru33336.c:11:24: warning: implicit conversion from 'double' to 'int' changes value from 3.141592653589793 to 3 [-Wliteral-conversion]
        printf("%g\n", myFunc(M_PI));
                       ~~~~~~ ^~~~
/usr/include/math.h:149:15: note: expanded from macro 'M_PI'
#define M_PI            3.14159265358979323846  /* pi */
                        ^~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
$ _

So you can see that an automatic conversion is being made to convert the double passed to the function into an int, to comply with the parameter type.  If you run the program, you'll get just
$ pru
3
$ _

redpajama_set_name: RedPajamaStackExchange


text:
...tick... tick... tick...
Decrease quantity for ...tick... tick... tick...
Increase quantity for ...tick... tick... tick...
ACTORS : Jim Brown, George Kennedy, Fredric March
YEAR OF RELEASE : 1970 RUNNING TIME : 100 min LANGUAGE : English Color
(Manufactured On Demand , Region 0.) This DVD will play in DVD players worldwide
POSTAGE : Free In Australia. Rest Of The World at Table Rate
Australia : All orders of two or more DVDs are upgraded to Tracked Shipping.
Rest Of The World : All orders shipped with Tracking
Delivery times for tracked shipping are halved compared to untracked shipping
Australia 7 to 15 days : Overseas 18 to 22 days
COMBINED POSTAGE : ONLY CHARGED FOR FIRST DVD ALL OTHERS IN A MULTIPLE ORDER ARE POST FREE
All DVDs come in a DVD case with color artwork and printed disc.
ALL DVDs ARE AVAILABLE ON Mpeg4 DOWNLOAD FILE
…tick… tick This is the story of a black man who has been elected sheriff in a U.S. southern county, due to the vote of blacks. He receives a huge amount of hostility from the non-tolerant white establishment, making his job very hard. The white former sheriff has his own struggle, as he balances his devotion to the law with his family and community relations. Things come to a head when the black sheriff puts a white man, the son of a wealthy land-owner of a neighboring county, in jail, and his daddy comes after him. Everyone around has to decide where their values really lie.
Surprisingly good
…tick… tick Film-critic Leonard Maltin called this "a poor man's In the Heat of the Night", which sounds like an easy way to dismiss a movie that is actually quite good on it's own terms, and not really anywhere close "In the Heat of the Night" story-wise (except for the part of white southerners learning to respect a black man).
In my opinion, Jim Brown is one of the coolest athletes-turned-actors of his generation. Sure, he's no Sidney Poitier, but who is? Here he's given one of the best parts of his career, and he even gets great support from a number of wonderful actors, notably the legendary Fredric March, who chews the scenery as a quarrelsome old mayor and George Kennedy as the former sheriff (and I guess this movie's equivalent to Rod Steiger if Leonard Maltin had a say in it). Don Stroud (whatever happened to his career?) is creepy as a racist ex-deputy and any fan of Clifton James should get a kick out of his part, as a leading klan-member who in the end turns out to be one of the main characters in the plot, and not such a bad guy after all.
A surprisingly engaging movie, at times quite gripping, with inspired direction by Ralph Nelson and a show of force from a first-rate cast.
The Naked Jungle


We are highly acclaimed in the industry for manufacturing, exporting and supplying an optimum quality range of Radiators Locomotives.
- Installed in locomotives to transfer thermal energy from one medium to another for the purpose of cooling.
We are supplier, manufacturer and exporter of wide range of Locomotive Components. These are made from superior quality raw material and are available in different sizes and shapes.
Scalable for installation of additional sub-systems in future for 'New Driver Cabs' or 'Modernization of Old Vehicles', driver consoles are designed to suit the vehicle design and to improve the driver's safety, comfort and effectiveness.
Material Grade: AS PER P.O.
Fabricated box like structure made of Sheet and Rolled Section. Used for carrying sand in locomotive.
Apart from above major items our product range for locomotive cover many others as ordered by our different customers time to time.
This is a composite test rack where all the WABCO Brake Valves can be tested by using separate test plates for individual Brake Valves.
- The name for the group company 'alicon' is coined from the words 'aluminum' and 'ikon''. alicon is a conglomerate that reflects a group of companies coming together to form a large, trusted and respectable entity with the vision and passion to go with it.
A huge range of Locomotive Components are offered by us to customers. The offered Locomotive Components are available in the market in various specifications and one can purchase these products at market leading rates. Locomotive Components are extensively used in electric locomotive traction.
We are engaged in manufacturing and supplier a wide range of products like locomotive components.
Locomotive, metro & EMU wheel set (with fittings and assemblies). We are capable to offer wheel sets for locomotives, metros, EMUS with all fittings and sub assemblies such as suspension / braking systems mounted.


text:
layout: post
title:  "Application URI protocol on Windows"
date:   2015-01-03 12:00:00
categories: windows
comments: True
description: How to register my app on Windows to be openned from a browser link using Application URI protocol.
---

There is a feature that we can use to make links on browser that can open specific applications registered to that kind of uri. For example, if you want to open itunes from the safari browser on a Mac, just type **[itmss://](itmss://)** on the address and hit enter.

If you want to do this on Windows, you need to register an application URI on the *register*. Programatically, you can do this using the following snippet in C#:

```csharp
RegistryKey key = Registry.ClassesRoot.OpenSubKey("appurltest");  //open appurltest subkey
if (key == null)  // checks if the protocol is already registered
{
    key = Registry.ClassesRoot.CreateSubKey("appurltest");
    key.SetValue(string.Empty, "URL: appurltest Protocol");
    key.SetValue("URL Protocol", string.Empty);
    key = key.CreateSubKey(@"shell\open\command");
    key.SetValue(string.Empty, myAppPath + " " + "%1");
    //%1 is the argument that will be passed to the application
}
key.Close();
```

After registered, you can open the app with a [link like this one](appurltest:Testing!).

[Simple example code on Github](https://github.com/anishihara/app_uri_on_windows).

##Resources:

* [Registering an Application to a URI Scheme - MSDN](http://msdn.microsoft.com/en-us/library/ie/aa767914(v=vs.85).aspx)
* [C# Register a Url Protocol](http://www.codingvision.net/miscellaneous/c-register-a-url-protocol)
* [Custom URL Protocol for Invoking Application - CodeProject](http://www.codeproject.com/Articles/332206/Custom-URL-Protocol-for-Invoking-Application)

redpajama_set_name: RedPajamaGithub


We have transformed many homes in the Belfast area with our quality windows, doors and conservatories. With over 60 years of experience, we know what works and can advise on any aspect of your home improvements. From improving the energy efficiency to boosting your kerb appeal, we can make you fall in love with your home again.
Your Belfast home will have never looked better. From high-quality PVC and aluminium to beautiful timber effect windows and bi-fold doors, we can make you the envy of your street. With our stylish range, there is something to suit every taste and budget.
We promise we have the right solutions for you. Whether you live in one of the many Victorian or Edwardian houses that fill the city or a period home in the suburbs. We are fully experienced with any style of home and whether you want to modernise or retain your traditional charm; we can help.
Belfast has always been a fastmoving city and continues to see development and expansion. Situated on the River Lagan and Belfast Lough made it an ideal place to become one of the biggest shipbuilding hubs in the world. Belfast harbour has gone through a massive regeneration in recent years with the introduction of the Titanic Quarter. This is home to film studios and apartments as well as a centre dedicated to the tragic ocean liner that was built here.
We have the right products perfect for your home. Suitable for the stunning Edwardian style new builds in Belvoir Park as well as a city centre townhouse. From composite doors to a beautiful glazed extension; we can improve the look of your home as well as how you use it.
Our service always put our customers at the forefront of everything we do. From honest advice to dedicated aftercare, we will do our upmost to provide you with the glazing solutions you need.
We are fully accredited by the GGF and Trustmark and have a host of brilliant testimonials from our many happy customers. Turkington Windows & Conservatories are the name you can trust for your Belfast home.


We are getting a first look at Paul Pogba's latest signature boot release, and his fifth collection with adidas. Pogba scored two penalties on Saturday wearing the new Predator 19+ PP, giving them a pretty successful debut.
Inspired by his passion of basketball, this latest collection features shades of White/Red/Black – perfect colors to go along with the Manchester United kit. As well as the boots, there are six further apparel pieces that go alongside a complete Pogba branded footwear pack.
Everything is set to officially release tomorrow! Stay tuned for availability details and prices.
These shoes look so awesome…!


text:
<?xml version="1.0" encoding="UTF-8"?>
<beans xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop">

    <!-- Configures database connection pool used to establish and manage connections to a content
         database. It is required to support interaction between database server and application
    -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="user" value="${database.username}"/>
        <property name="password" value="${database.password}"/>
        <property name="jdbcUrl" value="${database.jdbc.url}"/>
        <property name="driverClass" value="${database.driver.class}"/>
        <property name="maxPoolSize" value="${database.max.pool.size}"/>
        <property name="initialPoolSize" value="${database.initial.pool.size}"/>
    </bean>

    <!-- Enables the annotations-based configuration for transactional behavior  -->
    <aop:config proxy-target-class="true"/>
    <tx:annotation-driven transaction-manager="txManager"/>
    <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="txManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- Registers JdbcTemplate bean to use it among all DAO instances -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- Imports definitions for all DAOs -->
    <import resource="classpath:conf/catgenome/dao/dao-helper.xml"/>
    <import resource="classpath:conf/catgenome/dao/reference-genome-dao.xml"/>
    <import resource="classpath:conf/catgenome/dao/vcf-file-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/bam-file-dao.xml"/>
    <import resource="classpath:conf/catgenome/dao/gene-file-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/biological-data-item-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/project-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/project-description-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/blast-task-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/blast-database-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/bed-graph-file-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/person-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/bookmark-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/bucket-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/bed-file-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/seg-file-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/maf-file-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/url-shorter-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/species-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/user-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/role-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/activity-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/metadata-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/homolog-gene-alias-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/homolog-gene-description-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/homolog-gene-domain-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/homolog-database-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/homolog-group-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/homolog-group-gene-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/session-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/heatmap-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/lineage-tree-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/lineage-tree-node-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/lineage-tree-edge-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/pathway-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/pathway-organism-dao.xml" />
    <import resource="classpath:conf/catgenome/dao/bam-coverage-dao.xml" />
</beans>


text:
Kristi O'Connor
Kristi O'Connor reports out of WBTV's South Carolina bureau and anchors WBTV Saturday Morning.
Recent Articles by Kristi
Death doulas provide emotional support, education during the process of dying
Expecting mothers often enlist the help of birth doula to provide emotional support and education throughout their pregnancy. Now, end of life doulas are becoming popular for people whose loved ones are nearing death.
Lake Wylie woman pleads guilty to fatally poisoning husband with eye drops
A Lake Wylie woman accused of fatally poisoning her husband with eye drops pleaded guilty in court Thursday.
Piedmont Medical Center to open freestanding emergency room in Fort Mill
In just over a week, residents in Fort Mill who need an emergency room won't have to travel as far.
Gaston County woman receives medical bill more than a year later, too late to file appeal
A Gaston County woman spent nearly eight months disputing a medical bill she received nearly a year and a half after she received emergency room care. After contacting WBTV, her medical bill was forgiven.
Elderberry syrup gaining popularity in fight against cold and flu
Some people are turning to a centuries-old home remedy to protect themselves from the cold and flu this year, and nutritionists say it works.
Hickory, N.C. woman and baby survive after mom suffers rare heart attack mid-pregnancy
Brittany Little was about to become a mother for the third time when she had an unexpected heart attack that jeopardized both her and her unborn daughter's lives.
Published December 30, 2019 at 3:31 PM
Two dead, one seriously hurt in Gaston County crash
The North Carolina Highway Patrol is investigating a crash that left two people dead and another with serious injuries late Saturday night.
Charlotte BBB cautions public from committing to New Years resolution contracts right away
As 2020 approaches, many people will sign up for a gym membership to achieve their New Year resolutions. The Better Business Bureau of Charlotte recommends doing these things before signing a contract.
NICU nurse spends fifth Christmas with former patient who is now her son
Alex Tatsis has been a NICU nurse for 32 years and has cared for thousands of babies during her career. In 2014, one baby changed her life forever.
Proposed change to N.C. rule could pave way to better access to dental care
Under the proposed changes to the prior exam rule, a dentist would not have to be present to supervise a dental hygienist who is providing care to a patient who has not met the prior exam requirement.
Published December 19, 2019 at 12:43 PM
Retailers meet customer demands by providing products made with safer chemicals
Chemicals are in everything we use; from the food we eat to the car seats we put our children in. Some families in the Carolinas and across the country are becoming more cognizant of what makes up the products they use every day.
Mecklenburg County among the first in the country where nationwide HIV plan is implemented
The U.S. government announced a plan to reduce the number of new HIV infections by 90 percent in the next 10 years. The plan is called "Ending the HIV Epidemic: A Plan for America." It will be rolled out in 50 locations first; Mecklenburg County is one of those locations.
Homeless woman thankful for her health, after getting free access to care
A homeless woman in Charlotte is thankful for access to free healthcare this Thanksgiving.
Nonsmoking lung cancer patient aims to reduce stigma, raise awareness for more research
A Fort Mill man has been thriving for the past three years after a Stage 4 lung cancer diagnosis. He says one of the most frustrating parts of having lung cancer is the stigma that surrounds it.
Published November 24, 2019 at 11:50 AM
North Carolina infant mortality rates reach 31-year-low
Infant mortality rates in North Carolina reached at 31-year-low in 2018. According to the state infant mortality report, there were 6.8 deaths per 1,000 live births.
S.C. veteran pushes for change after cancer goes undiagnosed by Army for more than 2 years
A veteran from York County, SC is joining other veterans who are backing proposed legislation that would allow service members to sue for medical malpractice.
Published November 22, 2019 at 6:59 PM
Pediatric cancer cure rates improving, more research to be done locally
Levine Children's Hospital has been a part of clinical trials for more than a decade. One doctor says they are getting closer, but more research and resources are needed to improve survival rates even further.
York County woman addicted to opiates finds hope in new drug rehabilitation program
Officials in the York County judicial system are trying something out of the box in an effort to combat the opioid epidemic.
Shooting victim pronounced dead in hallway of uptown Charlotte apartments
Charlotte-Mecklenburg Police are investigating Charlotte' 93rd homicide of 2019.
Novant Health's TytoHome to expand virtual care
Novant Health is expanding access to healthcare using a device called TytoHome.
Published November 8, 2019 at 11:39 AM
Consuming dietary supplements not approved by the FDA a gamble for athletes
Dietary supplements are prominent in use among athletes and those who exercise. But many consumers may not know what makes up the products they're taking.
Published November 7, 2019 at 3:09 PM
OrthoCarolina physician assistant a driving force behind NASCAR race teams
OrthoCarolina's Dr. Bill Heisel embarked on uncharted territory when he started caring for race teams 15 years ago. Now, he's become a vital part of the sport.
Open enrollment for health insurance on the public marketplace begins Friday
Open enrollment for health insurance on the public marketplace begins Friday, November 1. Americans will have until December 15 to enroll for coverage in 2020.
CMPD investigates homicide in south Charlotte
Charlotte Mecklenburg Police are investigating a homicide in South Charlotte.
Kristi O'Connor and WBTV Web Staff
Doctors say it's safe for expecting moms and breastfeeding moms to get the flu shot
According to the CDC, only about 50 percent of expecting mothers received the flu shot in the 2016-2017 flu season. Physicians with Atrium Health are urging more expecting mothers to get vaccinated.
Atrium Health surgeons demonstrate use of robots in surgery on jack-o-lantern
Surgeons with Atrium Health are using robots to help them be more accurate and less invasive in surgery.
HPV vaccine a decade later shows drastic drop in infection and cancer rates, doctors say it could get better
It's been 12 years since the HPV vaccine has been on the market. Its effectiveness has been documented through shrinking infection rates, but physicians say the numbers could be better if everyone were to get vaccinated.
Novant Health utilizes new technology to detect strokes quicker
Novant Health is utilizing new technology to help physicians detect and treat a specific type of stroke faster. By cutting down the time to diagnose the stroke, they hope to see patients make better recoveries.
Portions of Brookshire Blvd. shut down after pedestrian struck and killed in accident
Portions of Brookshire Boulevard were shutdown early Saturday morning as CMPD investigated an a deadly accident involving a pedestrian.


text:
from __future__ import absolute_import

import codecs
import os
import sys
import threading

import serial
from serial.tools.list_ports import comports
from serial.tools import hexlify_codec

# pylint: disable=wrong-import-order,wrong-import-position

codecs.register(lambda c: hexlify_codec.getregentry() if c == 'hexlify' else None)

try:
    raw_input
except NameError:
    # pylint: disable=redefined-builtin,invalid-name
    raw_input = input   # in python3 it's "raw"
    unichr = chr

def key_description(character):
    """generate a readable description for a key"""
    ascii_code = ord(character)
    if ascii_code < 32:
        return 'Ctrl+{:c}'.format(ord('@') + ascii_code)
    else:
        return repr(character)

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class ConsoleBase(object):
    """OS abstraction for console (input/output codec, no echo)"""

    def __init__(self):
        if sys.version_info >= (3, 0):
            self.byte_output = sys.stdout.buffer
        else:
            self.byte_output = sys.stdout
        self.output = sys.stdout

    def setup(self):
        """Set console to read single characters, no echo"""

    def cleanup(self):
        """Restore default console settings"""

    def getkey(self):
        """Read a single key from the console"""
        return None

    def write_bytes(self, byte_string):
        """Write bytes (already encoded)"""
        self.byte_output.write(byte_string)
        self.byte_output.flush()

    def write(self, text):
        """Write string"""
        self.output.write(text)
        self.output.flush()

    def cancel(self):
        """Cancel getkey operation"""

    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
    # context manager:
    # switch terminal temporary to normal mode (e.g. to get user input)

    def __enter__(self):
        self.cleanup()
        return self

    def __exit__(self, *args, **kwargs):
        self.setup()

if os.name == 'nt':  # noqa
    import msvcrt
    import ctypes
    import platform

    class Out(object):
        """file-like wrapper that uses os.write"""

        def __init__(self, fd):
            self.fd = fd

        def flush(self):
            pass

        def write(self, s):
            os.write(self.fd, s)

    class Console(ConsoleBase):
        fncodes = {
            ';': '\1bOP',  # F1
            '<': '\1bOQ',  # F2
            '=': '\1bOR',  # F3
            '>': '\1bOS',  # F4
            '?': '\1b[15~',  # F5
            '@': '\1b[17~',  # F6
            'A': '\1b[18~',  # F7
            'B': '\1b[19~',  # F8
            'C': '\1b[20~',  # F9
            'D': '\1b[21~',  # F10
        }
        navcodes = {
            'H': '\x1b[A',  # UP
            'P': '\x1b[B',  # DOWN
            'K': '\x1b[D',  # LEFT
            'M': '\x1b[C',  # RIGHT
            'G': '\x1b[H',  # HOME
            'O': '\x1b[F',  # END
            'R': '\x1b[2~',  # INSERT
            'S': '\x1b[3~',  # DELETE
            'I': '\x1b[5~',  # PGUP
            'Q': '\x1b[6~',  # PGDN
        }

        def __init__(self):
            super(Console, self).__init__()
            self._saved_ocp = ctypes.windll.kernel32.GetConsoleOutputCP()
            self._saved_icp = ctypes.windll.kernel32.GetConsoleCP()
            ctypes.windll.kernel32.SetConsoleOutputCP(65001)
            ctypes.windll.kernel32.SetConsoleCP(65001)
            # ANSI handling available through SetConsoleMode since Windows 10 v1511
            # https://en.wikipedia.org/wiki/ANSI_escape_code#cite_note-win10th2-1
            if platform.release() == '10' and int(platform.version().split('.')[2]) > 10586:
                ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
                import ctypes.wintypes as wintypes
                if not hasattr(wintypes, 'LPDWORD'): # PY2
                    wintypes.LPDWORD = ctypes.POINTER(wintypes.DWORD)
                SetConsoleMode = ctypes.windll.kernel32.SetConsoleMode
                GetConsoleMode = ctypes.windll.kernel32.GetConsoleMode
                GetStdHandle = ctypes.windll.kernel32.GetStdHandle
                mode = wintypes.DWORD()
                GetConsoleMode(GetStdHandle(-11), ctypes.byref(mode))
                if (mode.value & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == 0:
                    SetConsoleMode(GetStdHandle(-11), mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
                    self._saved_cm = mode
            self.output = codecs.getwriter('UTF-8')(Out(sys.stdout.fileno()), 'replace')
            # the change of the code page is not propagated to Python, manually fix it
            sys.stderr = codecs.getwriter('UTF-8')(Out(sys.stderr.fileno()), 'replace')
            sys.stdout = self.output
            self.output.encoding = 'UTF-8'  # needed for input

        def __del__(self):
            ctypes.windll.kernel32.SetConsoleOutputCP(self._saved_ocp)
            ctypes.windll.kernel32.SetConsoleCP(self._saved_icp)
            try:
                ctypes.windll.kernel32.SetConsoleMode(ctypes.windll.kernel32.GetStdHandle(-11), self._saved_cm)
            except AttributeError: # in case no _saved_cm
                pass

        def getkey(self):
            while True:
                z = msvcrt.getwch()
                if z == unichr(13):
                    return unichr(10)
                elif z is unichr(0) or z is unichr(0xe0):
                    try:
                        code = msvcrt.getwch()
                        if z is unichr(0):
                            return self.fncodes[code]
                        else:
                            return self.navcodes[code]
                    except KeyError:
                        pass
                else:
                    return z

        def cancel(self):
            # CancelIo, CancelSynchronousIo do not seem to work when using
            # getwch, so instead, send a key to the window with the console
            hwnd = ctypes.windll.kernel32.GetConsoleWindow()
            ctypes.windll.user32.PostMessageA(hwnd, 0x100, 0x0d, 0)

elif os.name == 'posix':
    import atexit
    import termios
    import fcntl

    class Console(ConsoleBase):
        def __init__(self):
            super(Console, self).__init__()
            self.fd = sys.stdin.fileno()
            self.old = termios.tcgetattr(self.fd)
            atexit.register(self.cleanup)
            if sys.version_info < (3, 0):
                self.enc_stdin = codecs.getreader(sys.stdin.encoding)(sys.stdin)
            else:
                self.enc_stdin = sys.stdin

        def setup(self):
            new = termios.tcgetattr(self.fd)
            new[3] = new[3] & ~termios.ICANON & ~termios.ECHO & ~termios.ISIG
            new[6][termios.VMIN] = 1
            new[6][termios.VTIME] = 0
            termios.tcsetattr(self.fd, termios.TCSANOW, new)

        def getkey(self):
            c = self.enc_stdin.read(1)
            if c == unichr(0x7f):
                c = unichr(8)    # map the BS key (which yields DEL) to backspace
            return c

        def cancel(self):
            fcntl.ioctl(self.fd, termios.TIOCSTI, b'\0')

        def cleanup(self):
            termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.old)

else:
    raise NotImplementedError(
        'Sorry no implementation for your platform ({}) available.'.format(sys.platform))

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

class Transform(object):
    """do-nothing: forward all data unchanged"""
    def rx(self, text):
        """text received from serial port"""
        return text

    def tx(self, text):
        """text to be sent to serial port"""
        return text

    def echo(self, text):
        """text to be sent but displayed on console"""
        return text

class CRLF(Transform):
    """ENTER sends CR+LF"""

    def tx(self, text):
        return text.replace('\n', '\r\n')

class CR(Transform):
    """ENTER sends CR"""

    def rx(self, text):
        return text.replace('\r', '\n')

    def tx(self, text):
        return text.replace('\n', '\r')

class LF(Transform):
    """ENTER sends LF"""

class NoTerminal(Transform):
    """remove typical terminal control codes from input"""

    REPLACEMENT_MAP = dict((x, 0x2400 + x) for x in range(32) if unichr(x) not in '\r\n\b\t')
    REPLACEMENT_MAP.update(
        {
            0x7F: 0x2421,  # DEL
            0x9B: 0x2425,  # CSI
        })

    def rx(self, text):
        return text.translate(self.REPLACEMENT_MAP)

    echo = rx

class NoControls(NoTerminal):
    """Remove all control codes, incl. CR+LF"""

    REPLACEMENT_MAP = dict((x, 0x2400 + x) for x in range(32))
    REPLACEMENT_MAP.update(
        {
            0x20: 0x2423,  # visual space
            0x7F: 0x2421,  # DEL
            0x9B: 0x2425,  # CSI
        })

class Printable(Transform):
    """Show decimal code for all non-ASCII characters and replace most control codes"""

    def rx(self, text):
        r = []
        for c in text:
            if ' ' <= c < '\x7f' or c in '\r\n\b\t':
                r.append(c)
            elif c < ' ':
                r.append(unichr(0x2400 + ord(c)))
            else:
                r.extend(unichr(0x2080 + ord(d) - 48) for d in '{:d}'.format(ord(c)))
                r.append(' ')
        return ''.join(r)

    echo = rx

class Colorize(Transform):
    """Apply different colors for received and echo"""

    def __init__(self):
        # XXX make it configurable, use colorama?
        self.input_color = '\x1b[37m'
        self.echo_color = '\x1b[31m'

    def rx(self, text):
        return self.input_color + text

    def echo(self, text):
        return self.echo_color + text

class DebugIO(Transform):
    """Print what is sent and received"""

    def rx(self, text):
        sys.stderr.write(' [RX:{!r}] '.format(text))
        sys.stderr.flush()
        return text

    def tx(self, text):
        sys.stderr.write(' [TX:{!r}] '.format(text))
        sys.stderr.flush()
        return text

# other ideas:
# - add date/time for each newline
# - insert newline after: a) timeout b) packet end character

EOL_TRANSFORMATIONS = {
    'crlf': CRLF,
    'cr': CR,
    'lf': LF,
}

TRANSFORMATIONS = {
    'direct': Transform,    # no transformation
    'default': NoTerminal,
    'nocontrol': NoControls,
    'printable': Printable,
    'colorize': Colorize,
    'debug': DebugIO,
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def ask_for_port():
    """\
    Show a list of ports and ask the user for a choice. To make selection
    easier on systems with long device names, also allow the input of an
    index.
    """
    sys.stderr.write('\n--- Available ports:\n')
    ports = []
    for n, (port, desc, hwid) in enumerate(sorted(comports()), 1):
        sys.stderr.write('--- {:2}: {:20} {!r}\n'.format(n, port, desc))
        ports.append(port)
    while True:
        port = raw_input('--- Enter port index or full name: ')
        try:
            index = int(port) - 1
            if not 0 <= index < len(ports):
                sys.stderr.write('--- Invalid index!\n')
                continue
        except ValueError:
            pass
        else:
            port = ports[index]
        return port

class Miniterm(object):
    """\
    Terminal application. Copy data from serial port to console and vice versa.
    Handle special keys from the console to show menu etc.
    """

    def __init__(self, serial_instance, echo=False, eol='crlf', filters=()):
        self.console = Console()
        self.serial = serial_instance
        self.echo = echo
        self.raw = False
        self.input_encoding = 'UTF-8'
        self.output_encoding = 'UTF-8'
        self.eol = eol
        self.filters = filters
        self.update_transformations()
        self.exit_character = unichr(0x1d)  # GS/CTRL+]
        self.menu_character = unichr(0x14)  # Menu: CTRL+T
        self.alive = None
        self._reader_alive = None
        self.receiver_thread = None
        self.rx_decoder = None
        self.tx_decoder = None

    def _start_reader(self):
        """Start reader thread"""
        self._reader_alive = True
        # start serial->console thread
        self.receiver_thread = threading.Thread(target=self.reader, name='rx')
        self.receiver_thread.daemon = True
        self.receiver_thread.start()

    def _stop_reader(self):
        """Stop reader thread only, wait for clean exit of thread"""
        self._reader_alive = False
        if hasattr(self.serial, 'cancel_read'):
            self.serial.cancel_read()
        self.receiver_thread.join()

    def start(self):
        """start worker threads"""
        self.alive = True
        self._start_reader()
        # enter console->serial loop
        self.transmitter_thread = threading.Thread(target=self.writer, name='tx')
        self.transmitter_thread.daemon = True
        self.transmitter_thread.start()
        self.console.setup()

    def stop(self):
        """set flag to stop worker threads"""
        self.alive = False

    def join(self, transmit_only=False):
        """wait for worker threads to terminate"""
        self.transmitter_thread.join()
        if not transmit_only:
            if hasattr(self.serial, 'cancel_read'):
                self.serial.cancel_read()
            self.receiver_thread.join()

    def close(self):
        self.serial.close()

    def update_transformations(self):
        """take list of transformation classes and instantiate them for rx and tx"""
        transformations = [EOL_TRANSFORMATIONS[self.eol]] + [TRANSFORMATIONS[f]
                                                             for f in self.filters]
        self.tx_transformations = [t() for t in transformations]
        self.rx_transformations = list(reversed(self.tx_transformations))

    def set_rx_encoding(self, encoding, errors='replace'):
        """set encoding for received data"""
        self.input_encoding = encoding
        self.rx_decoder = codecs.getincrementaldecoder(encoding)(errors)

    def set_tx_encoding(self, encoding, errors='replace'):
        """set encoding for transmitted data"""
        self.output_encoding = encoding
        self.tx_encoder = codecs.getincrementalencoder(encoding)(errors)

    def dump_port_settings(self):
        """Write current settings to sys.stderr"""
        sys.stderr.write("\n--- Settings: {p.name}  {p.baudrate},{p.bytesize},{p.parity},{p.stopbits}\n".format(
            p=self.serial))
        sys.stderr.write('--- RTS: {:8}  DTR: {:8}  BREAK: {:8}\n'.format(
            ('active' if self.serial.rts else 'inactive'),
            ('active' if self.serial.dtr else 'inactive'),
            ('active' if self.serial.break_condition else 'inactive')))
        try:
            sys.stderr.write('--- CTS: {:8}  DSR: {:8}  RI: {:8}  CD: {:8}\n'.format(
                ('active' if self.serial.cts else 'inactive'),
                ('active' if self.serial.dsr else 'inactive'),
                ('active' if self.serial.ri else 'inactive'),
                ('active' if self.serial.cd else 'inactive')))
        except serial.SerialException:
            # on RFC 2217 ports, it can happen if no modem state notification was
            # yet received. ignore this error.
            pass
        sys.stderr.write('--- software flow control: {}\n'.format('active' if self.serial.xonxoff else 'inactive'))
        sys.stderr.write('--- hardware flow control: {}\n'.format('active' if self.serial.rtscts else 'inactive'))
        sys.stderr.write('--- serial input encoding: {}\n'.format(self.input_encoding))
        sys.stderr.write('--- serial output encoding: {}\n'.format(self.output_encoding))
        sys.stderr.write('--- EOL: {}\n'.format(self.eol.upper()))
        sys.stderr.write('--- filters: {}\n'.format(' '.join(self.filters)))

    def reader(self):
        """loop and copy serial->console"""
        try:
            while self.alive and self._reader_alive:
                # read all that is there or wait for one byte
                data = self.serial.read(self.serial.in_waiting or 1)
                if data:
                    if self.raw:
                        self.console.write_bytes(data)
                    else:
                        text = self.rx_decoder.decode(data)
                        for transformation in self.rx_transformations:
                            text = transformation.rx(text)
                        self.console.write(text)
        except serial.SerialException:
            self.alive = False
            self.console.cancel()
            raise       # XXX handle instead of re-raise?

    def writer(self):
        """\
        Loop and copy console->serial until self.exit_character character is
        found. When self.menu_character is found, interpret the next key
        locally.
        """
        menu_active = False
        try:
            while self.alive:
                try:
                    c = self.console.getkey()
                except KeyboardInterrupt:
                    c = '\x03'
                if not self.alive:
                    break
                if menu_active:
                    self.handle_menu_key(c)
                    menu_active = False
                elif c == self.menu_character:
                    menu_active = True      # next char will be for menu
                elif c == self.exit_character:
                    self.stop()             # exit app
                    break
                else:
                    #~ if self.raw:
                    text = c
                    for transformation in self.tx_transformations:
                        text = transformation.tx(text)
                    self.serial.write(self.tx_encoder.encode(text))
                    if self.echo:
                        echo_text = c
                        for transformation in self.tx_transformations:
                            echo_text = transformation.echo(echo_text)
                        self.console.write(echo_text)
        except:
            self.alive = False
            raise

    def handle_menu_key(self, c):
        """Implement a simple menu / settings"""
        if c == self.menu_character or c == self.exit_character:
            # Menu/exit character again -> send itself
            self.serial.write(self.tx_encoder.encode(c))
            if self.echo:
                self.console.write(c)
        elif c == '\x15':                       # CTRL+U -> upload file
            self.upload_file()
        elif c in '\x08hH?':                    # CTRL+H, h, H, ? -> Show help
            sys.stderr.write(self.get_help_text())
        elif c == '\x12':                       # CTRL+R -> Toggle RTS
            self.serial.rts = not self.serial.rts
            sys.stderr.write('--- RTS {} ---\n'.format('active' if self.serial.rts else 'inactive'))
        elif c == '\x04':                       # CTRL+D -> Toggle DTR
            self.serial.dtr = not self.serial.dtr
            sys.stderr.write('--- DTR {} ---\n'.format('active' if self.serial.dtr else 'inactive'))
        elif c == '\x02':                       # CTRL+B -> toggle BREAK condition
            self.serial.break_condition = not self.serial.break_condition
            sys.stderr.write('--- BREAK {} ---\n'.format('active' if self.serial.break_condition else 'inactive'))
        elif c == '\x05':                       # CTRL+E -> toggle local echo
            self.echo = not self.echo
            sys.stderr.write('--- local echo {} ---\n'.format('active' if self.echo else 'inactive'))
        elif c == '\x06':                       # CTRL+F -> edit filters
            self.change_filter()
        elif c == '\x0c':                       # CTRL+L -> EOL mode
            modes = list(EOL_TRANSFORMATIONS)   # keys
            eol = modes.index(self.eol) + 1
            if eol >= len(modes):
                eol = 0
            self.eol = modes[eol]
            sys.stderr.write('--- EOL: {} ---\n'.format(self.eol.upper()))
            self.update_transformations()
        elif c == '\x01':                       # CTRL+A -> set encoding
            self.change_encoding()
        elif c == '\x09':                       # CTRL+I -> info
            self.dump_port_settings()
        #~ elif c == '\x01':                       # CTRL+A -> cycle escape mode
        #~ elif c == '\x0c':                       # CTRL+L -> cycle linefeed mode
        elif c in 'pP':                         # P -> change port
            self.change_port()
        elif c in 'zZ':                         # S -> suspend / open port temporarily
            self.suspend_port()
        elif c in 'bB':                         # B -> change baudrate
            self.change_baudrate()
        elif c == '8':                          # 8 -> change to 8 bits
            self.serial.bytesize = serial.EIGHTBITS
            self.dump_port_settings()
        elif c == '7':                          # 7 -> change to 8 bits
            self.serial.bytesize = serial.SEVENBITS
            self.dump_port_settings()
        elif c in 'eE':                         # E -> change to even parity
            self.serial.parity = serial.PARITY_EVEN
            self.dump_port_settings()
        elif c in 'oO':                         # O -> change to odd parity
            self.serial.parity = serial.PARITY_ODD
            self.dump_port_settings()
        elif c in 'mM':                         # M -> change to mark parity
            self.serial.parity = serial.PARITY_MARK
            self.dump_port_settings()
        elif c in 'sS':                         # S -> change to space parity
            self.serial.parity = serial.PARITY_SPACE
            self.dump_port_settings()
        elif c in 'nN':                         # N -> change to no parity
            self.serial.parity = serial.PARITY_NONE
            self.dump_port_settings()
        elif c == '1':                          # 1 -> change to 1 stop bits
            self.serial.stopbits = serial.STOPBITS_ONE
            self.dump_port_settings()
        elif c == '2':                          # 2 -> change to 2 stop bits
            self.serial.stopbits = serial.STOPBITS_TWO
            self.dump_port_settings()
        elif c == '3':                          # 3 -> change to 1.5 stop bits
            self.serial.stopbits = serial.STOPBITS_ONE_POINT_FIVE
            self.dump_port_settings()
        elif c in 'xX':                         # X -> change software flow control
            self.serial.xonxoff = (c == 'X')
            self.dump_port_settings()
        elif c in 'rR':                         # R -> change hardware flow control
            self.serial.rtscts = (c == 'R')
            self.dump_port_settings()
        elif c in 'qQ':
            self.stop()                         # Q -> exit app
        else:
            sys.stderr.write('--- unknown menu character {} --\n'.format(key_description(c)))

    def upload_file(self):
        """Ask user for filenname and send its contents"""
        sys.stderr.write('\n--- File to upload: ')
        sys.stderr.flush()
        with self.console:
            filename = sys.stdin.readline().rstrip('\r\n')
            if filename:
                try:
                    with open(filename, 'rb') as f:
                        sys.stderr.write('--- Sending file {} ---\n'.format(filename))
                        while True:
                            block = f.read(1024)
                            if not block:
                                break
                            self.serial.write(block)
                            # Wait for output buffer to drain.
                            self.serial.flush()
                            sys.stderr.write('.')   # Progress indicator.
                    sys.stderr.write('\n--- File {} sent ---\n'.format(filename))
                except IOError as e:
                    sys.stderr.write('--- ERROR opening file {}: {} ---\n'.format(filename, e))

    def change_filter(self):
        """change the i/o transformations"""
        sys.stderr.write('\n--- Available Filters:\n')
        sys.stderr.write('\n'.join(
            '---   {:<10} = {.__doc__}'.format(k, v)
            for k, v in sorted(TRANSFORMATIONS.items())))
        sys.stderr.write('\n--- Enter new filter name(s) [{}]: '.format(' '.join(self.filters)))
        with self.console:
            new_filters = sys.stdin.readline().lower().split()
        if new_filters:
            for f in new_filters:
                if f not in TRANSFORMATIONS:
                    sys.stderr.write('--- unknown filter: {!r}\n'.format(f))
                    break
            else:
                self.filters = new_filters
                self.update_transformations()
        sys.stderr.write('--- filters: {}\n'.format(' '.join(self.filters)))

    def change_encoding(self):
        """change encoding on the serial port"""
        sys.stderr.write('\n--- Enter new encoding name [{}]: '.format(self.input_encoding))
        with self.console:
            new_encoding = sys.stdin.readline().strip()
        if new_encoding:
            try:
                codecs.lookup(new_encoding)
            except LookupError:
                sys.stderr.write('--- invalid encoding name: {}\n'.format(new_encoding))
            else:
                self.set_rx_encoding(new_encoding)
                self.set_tx_encoding(new_encoding)
        sys.stderr.write('--- serial input encoding: {}\n'.format(self.input_encoding))
        sys.stderr.write('--- serial output encoding: {}\n'.format(self.output_encoding))

    def change_baudrate(self):
        """change the baudrate"""
        sys.stderr.write('\n--- Baudrate: ')
        sys.stderr.flush()
        with self.console:
            backup = self.serial.baudrate
            try:
                self.serial.baudrate = int(sys.stdin.readline().strip())
            except ValueError as e:
                sys.stderr.write('--- ERROR setting baudrate: {} ---\n'.format(e))
                self.serial.baudrate = backup
            else:
                self.dump_port_settings()

    def change_port(self):
        """Have a conversation with the user to change the serial port"""
        with self.console:
            try:
                port = ask_for_port()
            except KeyboardInterrupt:
                port = None
        if port and port != self.serial.port:
            # reader thread needs to be shut down
            self._stop_reader()
            # save settings
            settings = self.serial.getSettingsDict()
            try:
                new_serial = serial.serial_for_url(port, do_not_open=True)
                # restore settings and open
                new_serial.applySettingsDict(settings)
                new_serial.rts = self.serial.rts
                new_serial.dtr = self.serial.dtr
                new_serial.open()
                new_serial.break_condition = self.serial.break_condition
            except Exception as e:
                sys.stderr.write('--- ERROR opening new port: {} ---\n'.format(e))
                new_serial.close()
            else:
                self.serial.close()
                self.serial = new_serial
                sys.stderr.write('--- Port changed to: {} ---\n'.format(self.serial.port))
            # and restart the reader thread
            self._start_reader()

    def suspend_port(self):
        """\
        open port temporarily, allow reconnect, exit and port change to get
        out of the loop
        """
        # reader thread needs to be shut down
        self._stop_reader()
        self.serial.close()
        sys.stderr.write('\n--- Port closed: {} ---\n'.format(self.serial.port))
        do_change_port = False
        while not self.serial.is_open:
            sys.stderr.write('--- Quit: {exit} | p: port change | any other key to reconnect ---\n'.format(
                exit=key_description(self.exit_character)))
            k = self.console.getkey()
            if k == self.exit_character:
                self.stop()             # exit app
                break
            elif k in 'pP':
                do_change_port = True
                break
            try:
                self.serial.open()
            except Exception as e:
                sys.stderr.write('--- ERROR opening port: {} ---\n'.format(e))
        if do_change_port:
            self.change_port()
        else:
            # and restart the reader thread
            self._start_reader()
            sys.stderr.write('--- Port opened: {} ---\n'.format(self.serial.port))

    def get_help_text(self):
        """return the help text"""
        # help text, starts with blank line!
        return """
--- pySerial ({version}) - miniterm - help
---
--- {exit:8} Exit program (alias {menu} Q)
--- {menu:8} Menu escape key, followed by:
--- Menu keys:
---    {menu:7} Send the menu character itself to remote
---    {exit:7} Send the exit character itself to remote
---    {info:7} Show info
---    {upload:7} Upload file (prompt will be shown)
---    {repr:7} encoding
---    {filter:7} edit filters
--- Toggles:
---    {rts:7} RTS   {dtr:7} DTR   {brk:7} BREAK
---    {echo:7} echo  {eol:7} EOL
---
--- Port settings ({menu} followed by the following):
---    p          change port
---    7 8        set data bits
---    N E O S M  change parity (None, Even, Odd, Space, Mark)
---    1 2 3      set stop bits (1, 2, 1.5)
---    b          change baud rate
---    x X        disable/enable software flow control
---    r R        disable/enable hardware flow control
""".format(version=getattr(serial, 'VERSION', 'unknown version'),
           exit=key_description(self.exit_character),
           menu=key_description(self.menu_character),
           rts=key_description('\x12'),
           dtr=key_description('\x04'),
           brk=key_description('\x02'),
           echo=key_description('\x05'),
           info=key_description('\x09'),
           upload=key_description('\x15'),
           repr=key_description('\x01'),
           filter=key_description('\x06'),
           eol=key_description('\x0c'))

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# default args can be used to override when calling main() from an other script
# e.g to create a miniterm-my-device.py
def main(default_port=None, default_baudrate=9600, default_rts=None, default_dtr=None):
    """Command line tool, entry point"""

    import argparse

    parser = argparse.ArgumentParser(
        description='Miniterm - A simple terminal program for the serial port.')

    parser.add_argument(
        'port',
        nargs='?',
        help='serial port name ("-" to show port list)',
        default=default_port)

    parser.add_argument(
        'baudrate',
        nargs='?',
        type=int,
        help='set baud rate, default: %(default)s',
        default=default_baudrate)

    group = parser.add_argument_group('port settings')

    group.add_argument(
        '--parity',
        choices=['N', 'E', 'O', 'S', 'M'],
        type=lambda c: c.upper(),
        help='set parity, one of {N E O S M}, default: N',
        default='N')

    group.add_argument(
        '--rtscts',
        action='store_true',
        help='enable RTS/CTS flow control (default off)',
        default=False)

    group.add_argument(
        '--xonxoff',
        action='store_true',
        help='enable software flow control (default off)',
        default=False)

    group.add_argument(
        '--rts',
        type=int,
        help='set initial RTS line state (possible values: 0, 1)',
        default=default_rts)

    group.add_argument(
        '--dtr',
        type=int,
        help='set initial DTR line state (possible values: 0, 1)',
        default=default_dtr)

    group.add_argument(
        '--non-exclusive',
        dest='exclusive',
        action='store_false',
        help='disable locking for native ports',
        default=True)

    group.add_argument(
        '--ask',
        action='store_true',
        help='ask again for port when open fails',
        default=False)

    group = parser.add_argument_group('data handling')

    group.add_argument(
        '-e', '--echo',
        action='store_true',
        help='enable local echo (default off)',
        default=False)

    group.add_argument(
        '--encoding',
        dest='serial_port_encoding',
        metavar='CODEC',
        help='set the encoding for the serial port (e.g. hexlify, Latin1, UTF-8), default: %(default)s',
        default='UTF-8')

    group.add_argument(
        '-f', '--filter',
        action='append',
        metavar='NAME',
        help='add text transformation',
        default=[])

    group.add_argument(
        '--eol',
        choices=['CR', 'LF', 'CRLF'],
        type=lambda c: c.upper(),
        help='end of line mode',
        default='CRLF')

    group.add_argument(
        '--raw',
        action='store_true',
        help='Do no apply any encodings/transformations',
        default=False)

    group = parser.add_argument_group('hotkeys')

    group.add_argument(
        '--exit-char',
        type=int,
        metavar='NUM',
        help='Unicode of special character that is used to exit the application, default: %(default)s',
        default=0x1d)  # GS/CTRL+]

    group.add_argument(
        '--menu-char',
        type=int,
        metavar='NUM',
        help='Unicode code of special character that is used to control miniterm (menu), default: %(default)s',
        default=0x14)  # Menu: CTRL+T

    group = parser.add_argument_group('diagnostics')

    group.add_argument(
        '-q', '--quiet',
        action='store_true',
        help='suppress non-error messages',
        default=False)

    group.add_argument(
        '--develop',
        action='store_true',
        help='show Python traceback on error',
        default=False)

    args = parser.parse_args()

    if args.menu_char == args.exit_char:
        parser.error('--exit-char can not be the same as --menu-char')

    if args.filter:
        if 'help' in args.filter:
            sys.stderr.write('Available filters:\n')
            sys.stderr.write('\n'.join(
                '{:<10} = {.__doc__}'.format(k, v)
                for k, v in sorted(TRANSFORMATIONS.items())))
            sys.stderr.write('\n')
            sys.exit(1)
        filters = args.filter
    else:
        filters = ['default']

    while True:
        # no port given on command line -> ask user now
        if args.port is None or args.port == '-':
            try:
                args.port = ask_for_port()
            except KeyboardInterrupt:
                sys.stderr.write('\n')
                parser.error('user aborted and port is not given')
            else:
                if not args.port:
                    parser.error('port is not given')
        try:
            serial_instance = serial.serial_for_url(
                args.port,
                args.baudrate,
                parity=args.parity,
                rtscts=args.rtscts,
                xonxoff=args.xonxoff,
                do_not_open=True)

            if not hasattr(serial_instance, 'cancel_read'):
                # enable timeout for alive flag polling if cancel_read is not available
                serial_instance.timeout = 1

            if args.dtr is not None:
                if not args.quiet:
                    sys.stderr.write('--- forcing DTR {}\n'.format('active' if args.dtr else 'inactive'))
                serial_instance.dtr = args.dtr
            if args.rts is not None:
                if not args.quiet:
                    sys.stderr.write('--- forcing RTS {}\n'.format('active' if args.rts else 'inactive'))
                serial_instance.rts = args.rts

            if isinstance(serial_instance, serial.Serial):
                serial_instance.exclusive = args.exclusive

            serial_instance.open()
        except serial.SerialException as e:
            sys.stderr.write('could not open port {!r}: {}\n'.format(args.port, e))
            if args.develop:
                raise
            if not args.ask:
                sys.exit(1)
            else:
                args.port = '-'
        else:
            break

    miniterm = Miniterm(
        serial_instance,
        echo=args.echo,
        eol=args.eol.lower(),
        filters=filters)
    miniterm.exit_character = unichr(args.exit_char)
    miniterm.menu_character = unichr(args.menu_char)
    miniterm.raw = args.raw
    miniterm.set_rx_encoding(args.serial_port_encoding)
    miniterm.set_tx_encoding(args.serial_port_encoding)

    if not args.quiet:
        sys.stderr.write('--- Miniterm on {p.name}  {p.baudrate},{p.bytesize},{p.parity},{p.stopbits} ---\n'.format(
            p=miniterm.serial))
        sys.stderr.write('--- Quit: {} | Menu: {} | Help: {} followed by {} ---\n'.format(
            key_description(miniterm.exit_character),
            key_description(miniterm.menu_character),
            key_description(miniterm.menu_character),
            key_description('\x08')))

    miniterm.start()
    try:
        miniterm.join(True)
    except KeyboardInterrupt:
        pass
    if not args.quiet:
        sys.stderr.write('\n--- exit ---\n')
    miniterm.join()
    miniterm.close()

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if __name__ == '__main__':
    main()