I'm new to this, but fascinated by the possibilities of this technology. I'm happy to turn my hand to most things, but I would appreciate a steer.
We have a UK three phase domestic supply. Our heat pump runs off three phase, but most of the other usage is currently on L2. We have three 4KW sets of PV panels, each feeding a single phase through an inverter.
I want to be able to separately monitor consumption and generation on each phase so that I can make better use of the electricity we generate, but it’s all guesswork at the moment as I have one import meter and two generation meters so insufficient data to do any analysis.
The problems:
1) We have two single and two three phase distribution boards, so the only way we can realistically work out our consumption is to measure and record a) the flow (which may be import or export) in the incomers at our import meter and b) generation at the three phase board that is fed by the inverters.
2) These two points (a & b) are less than 10 metres apart, but in different buildings and at best there is one 600mm stone wall between transmitters and receiver.
If I’ve understood the answers to previous questions correctly, I’ll need an AC input from each phase, plus a CT on each phase of generation and a CT on each of the three incomers.
My questions:
1) Will I need three emonTx to achieve this
2) If so, should I have a) one emonTx at the generation board measuring L1, L2, L3 current plus AC voltage on say L1, and b) two emonTx at the incomers to measure L1, L2, L3 import/export current and AC voltage on L2 and L3? ….or is this wrong, or is there a better way?
3) Can I expect the wireless signals to pass through a 600mm stone wall?
4) Can the emoncms software report on the three phases separately?
5) Should setting this up be within the capabilities of an enthusiastic novice?
I hope that was clear. I'd really appreciate some help.
Andy
Re: A newcomer – three phase, but it's a bit complicated
Ouch! I don't think the wireless has the remotest chance of getting through 600 mm of stone. With luck, I might be able to test that next week! If I have any success, I'll let you know. Before I draw a diagram of your set-up, I think you need to look at Martin Robert's "full fat" solution, if you've not already done so: http://openenergymonitor.org/emon/node/1170. This uses 3 emonTx V2s and should do all you ask, but you will need to bring the three generation c.t. cables through your stone wall for that to work. Some users have done this successfully, some have had problems, so it might not be plain sailing.
The problem with 2(a) is you can't realistically use the voltage measured on one emonTx in another because the phase relationship can't be maintained. Note, there's only one voltage input on any of the emonTx range. So you will be measuring the voltage on L1 and assuming the voltage on L2 and L3 matches that on L1, and that might or might not be the case, leading to a potential inaccuracy. You'd need to have exactly the same on both the incomer and the generation infeed, so two emonTx's.
Now the easy bits: 4 - Yes, you decide what you want to show; and 5 - it should be possible. You'll have help from these forums when you need it.
Re: A newcomer – three phase, but it's a bit complicated
Many thanks Robert, I'd previously looked at the full fat solution. So is bringing together all the CT outputs the only realistic way to make it work? If the wireless problem is the biggest one, there might be a way round that, but I think I'd better sketch out the setup to explain it better.
Re: A newcomer – three phase, but it's a bit complicated
Bringing all the c.t's to one place isn't absolutely necessary, but I was looking for the best engineering compromise that might be acceptable.
If you want to measure real power and the direction of energy flow (as I think you do), you must have voltage and current in the same place. If you have three phases, for accuracy you need voltage as well as current for each phase. If you are content to assume that the voltages of phases 2 & 3 accurately match phase 1 voltage, you need only measure one voltage, and you use the approximation 3-phase sketch that stores the voltage and uses it delayed to calculate the power for the other two phases.
So here are your options as I see them:
3 x emonTx on the incomer + 3 x emonTx on the PV infeed, accurately reading power.
3 x emonTx on the incomer (or PV infeed) with long cables on the 3 c.t's from the other, accurately reading power.
1 x emonTx on the incomer + 1 x emonTx on the PV infeed, each reading accurate power on L1 and approximate power on L2 & L3
2 x Arduino with Tinbum's front end - see http://openenergymonitor.org/emon/node/2674
[Edit - added 4th option, courtesy of Robin]
Re: A newcomer – three phase, but it's a bit complicated
I don't think that measuring voltage on one phase will be good enough, although it might be a good place to start. We are supplied from a small transformer feeding about 10 properties in total and I don't imagine the load is well balanced. I've no idea how heavily loaded it is. I ought to check the voltage data that the inverters have recorded.
I've attached a sketch to show our setup - I hope it makes sense. The distance from the incoming board 0 to board 3 is about 5m and from board 3 to 4 is about 6m.
Your first option - if I mounted three emonTx adjacent to board 3, I could pick up the voltage from that board, but could I run the CT sensors 5m from the incoming board (0)? What sort of cable would be required?
You've mentioned three emonTx to monitor the PV generated current. Is this because of the need to relate these currents to the voltage too, so another set of three voltage measurements?
Re: A newcomer – three phase, but it's a bit complicated
From what you say about the local distribution system, I think you're right in needing to measure the three phase voltages.
"What sort of cable would be required?" Ordinary twin twisted screened ("microphone") cable. Earth the screen at the c.t. end, don't connect it at the emonTx.
"Is this because of the need to relate these currents to the voltage too, so another set of three voltage measurements?" Indeed. (If you use one emonTx per phase and long cables, we hope that the voltage difference between boards 0 and 3 will be negligible, which should be the case unless you have a big load on boards 2, 3 or 4.)
Re: A newcomer – three phase, but it's a bit complicated
I've checked the voltage readings, and found all three phases to be around 250v +/- 3v during the time the inverters are active. I only have readings every 10 min from two of the phases so can't be sure of instantaneous discrepancies between phases. I guess there may be some phase shift as well as voltage variation with changes in load which I assume could all throw out calculated power measurements if I'm relying on just one phase for the AC.
OK, I think I've decided on a plan.
I shall start off with one emonTx on generation and one emonTx on the incomers, both linked to L3 because that's easiest. I'll try wireless connection and see how that goes. If I mount the incomer emonTx close to board 0, I can use an extension for the AC rather than the CT sensors. If the wireless can't cope, I'll extend the CT sensor leads.... or is installing an SMA RF connector and an extension to a remote antenna an option?
I'll develop this system depending on how the readings compare with the measured import and generated power.
So my shopping list:
Does that sounds reasonable? Is anything missing?
Re: A newcomer – three phase, but it's a bit complicated
What's the next step? If you think you might be going for three stacked emonTx's, then the V2 is the one Martin used. I've not looked at how the V3 might stack, it could well be not easy. If you have the V2, you need 2 more 5 V USB power supplies and leads.
Or instead of three emonTx's, you could have one Arduino and Tinbum's front end board.
I'm a bit concerned that you might be heading up a dead end.
Obviously there's provision for an SMA connector on the V3. I don't know about one for the V2, you'd need a very neat termination at the RFM12B end to maintain the impedance matching. I've no idea what cable length would be possible, but if you need only 600 mm plus a bit to get to the other side of the wall, I wouldn't anticipate a major problem.
I don't know exactly what you need to go with the RPi.
Re: A newcomer – three phase, but it's a bit complicated
If you're going for the V2 I'd also suggest getting a http://shop.openenergymonitor.com/programmer-usb-to-serial-uart/
Re: A newcomer – three phase, but it's a bit complicated
Oops - sorry, I missed that. Thanks, Mark.
Andy, have you seen Lighning's Raspberry Pi shield? http://openenergymonitor.org/emon/node/3877
I don't know a price for the shield. It could be a more economical way to go, and worth looking at if you haven't already done so.
Re: A newcomer – three phase, but it's a bit complicated
Sorry for the delay in responding; it's been a busy week.
As a complete beginner, I've concluded that I should go for as simple a solution as I can, even if it gives approximate rather than precise values. The key thing for me is going to be whether I'm importing or exporting, phase by phase, together with an indication of how much and the ability to record this. If I can achieve an accuracy of +/- 10%, I'll be content to start with. I also want to minimise the number of possible problem areas in the event of malfunctions.
For these reasons I think I need to go for ready-built parts that provide me with a reasonable development path without too much redundancy.
Given these constraints, what would you suggest?
Andy
Re: A newcomer – three phase, but it's a bit complicated
I'm away from home too at the moment, I'll try to put a scheme together for you by the end of the week.
Re: A newcomer – three phase, but it's a bit complicated
If you want to stay with ready-made parts, but you are prepared to compile and load some sketches, and you're prepared to accept some inaccuracy; then the cheapest and simplest starting point is an emonTx V3 on the grid connection and the same on the PV infeed. Each would run the approximation three-phase sketch and have one ac adapter for power and voltage monitoring, and three ct's for the three phase currents, from which real power per phase can be calculated. So the data available to you would be the true voltage for L1, the true line current for all 3 lines, the accurate real and apparent power and power factor for L1, and the approximate real and apparent power and power factor for L2 and L3 (though apparent power and power factor for generation is largely meaningless as it depends on the power factor of the national grid at your location, which you cannot influence).
To record this data, you need an emonBase. The established and proven unit is the NanodeRF used in conjunction with emoncms.org (and a connection to your router and the Internet of course). The alternative is a Raspberry Pi with the RF module, that can either be used to forward your data to emoncms.org, or with the addition of the emoncms software and a hard disk drive can store your data locally. This second option requires a knowledge of the RPi and is less well established.
If you're going re-program the emonTx V3, or program a NanodeRF, you'll need a programmer.
Unfortunately, the development path isn't a direct one. The neatest solution for 3-phase monitoring of both grid and PV is Martin Robert's "full-fat" scheme. That would mean building 3 emonTx V2's and your two V3's would be redundant. The alternative, using your two V3's would be to add a third V3 and link the power supplies and serial lines, but unfortunately that is not easy as one serial line shares a pin with the CT4 input (if I've read the schematic correctly), so I wouldn't recommend it if you're not happy doing a serious modification to the pcb.
So it does look very much like Plan A plus a programmer to start with, but I can't make a firm recommendation for the upgrade path.
Re: A newcomer – three phase, but it's a bit complicated
"3) Can I expect the wireless signals to pass through a 600mm stone wall?"
I thought the answer was a firm "no", but it might well be a yes. Last week I installed an emon system (for now, an emonTx V2 and emonGLCD, working at 868 MHz) at a friend's Scottish farmhouse. The emonTx is behind glass in a barn window, which is about 18 m across the garden from the kitchen. The GLCD is fixed to the inside face of the 600 mm kitchen wall that faces the barn, but nowhere near a direct line of sight, it is about 600 mm away from the lower corner of the window.
The two ct's are each on the end of 10 m of twin screened microphone cable, with the screen earthed at the ct end.
And it's all working fine. I didn't check the grid c.t. against the revenue meter, but having calibrated the PV ct and voltage adapter against my multimeter, the emonTx was within 50 W of the inverter display at 2 kW. (And that's a lot closer than his Efergy display.)
Re: A newcomer – three phase, but it's a bit complicated
At last I'm getting round to ordering the kit for monitoring just import/export to start with; I'll add the generation side once I've got this working. Being unfamiliar with everything, I feel more comfortable with this approach.
Re: A newcomer – three phase, but it's a bit complicated
The kit has arrived. I understand that the Tx V3 already has the firmware loaded. There's an enormous amount of information, but what exactly do I need to do with the Nanode? I will be measuring current on all three phases and voltage on L2 which carries the highest load, so I'll be using the approximation method of working out voltage on L1 and L3. I have Arduino IDE and the libraries installed on my PC. Could someone let me have step by step instructions, or point me to which instructions I need to follow? I'd be very grateful.
Re: A newcomer – three phase, but it's a bit complicated
First, your emonTx won't have the three-phase sketch loaded, but let's not worry about that for now. It won't make any difference until you set up your feeds and customise emoncms.
I assume you will be using emoncms.org?
You need to create an account at emoncms.org, customise some software for your Nanode, then load it. Connect the Nanode to your router with an Ethernet jumper cable, and see if the data appears as inputs at emoncms. Those are the big steps.
The little steps are:
1. Test the radio link between your emonTx and the Nanode. To do that, take my test sketch (attached), change the frequency if necessary - it's set to 868 MHz as it comes - and load the sketch. It should give a steady red LED if nothing is received after 20 s, or a green flash every time something is received. You can see what is received if you plug in to the serial output.
IT DOES NOTHING WITH THE ETHERNET - so there is only the one level of confusion!
2. Create an account at emoncms.org. Do all the usual stuff, then go to Input and Input API Helper. On that page, you'll see two API Keys. You need the READ & WRITE one to give your Nanode permission to write into the database.
3. Go to Github and get the appropriate sketch: https://github.com/openenergymonitor/NanodeRF/tree/master/NanodeRF_multi... (all 3 files, put them in a folder of the same name in your Arduino Sketchbook). Edit the main file and put your R&W Apikey where it says "YOURAPIKEY". I think everything else should be OK.
4. Load the sketch into the Nanode, connect the Ethernet and hope! It may take several tens of seconds to negotiate with your router and establish the connection. If you don't eventually see "OK recieved", then it's not working.
My "full" guide is the second attached file, with all the gory details and what you expect to see.
At your account in emoncms.org, you should see a few inputs pop up, matching the values sent by your emonTx. If that works, you can then load the 3-phase sketch and get that going too.
Re: A newcomer – three phase, but it's a bit complicated
Thanks for those very helpful instructions. I managed to follow them and now have data appearing in emoncms. I've attached what I'm seeing. The voltage seems reasonable although it's slightly high compared with what the inverter is showing (254v). I have set the Tx to read voltage on L2 and current on L1-3 at a point where I would expect the load/output to be about the same across all three phases. Is there something else I should be doing to read power in emoncms or is there something amiss?
I've tried placing the Tx about 8m and two thick stone walls from the Nanode and managed to get a signal across, although it seems to struggle if I increase the distance slightly and add another wall in.
On a slightly different subject, I recognise that if I'm going to place a CT some distance from the Tx, I need to replace the lead with a longer screened one. I've realised that it may be better to extend the AC-AC power supply lead and place the Tx at the main incomer. Would extending this lead to feed from a convenient 13A socket cause problems?
Re: A newcomer – three phase, but it's a bit complicated
OK, so the system is working, you're just not measuring the right things in the right way.
First, there's absolutely no problem with extending the "9 V" ac feed from the adapter.
I presume the sketch in your emonTx is still the default one - emonTxV3_RFM12B_DiscreteSampling. Obviously (or perhaps not!) that is for single phase only, so you need to get the 3-phase version. That is "emonTxV3_3Phase_Voltage" and it's in the EmonTx V3 - RFM12B - Examples folder on Github. Please read the comments at the beginning, they describe how it operates and what you need to do to calibrate it. It presumes the phase sequence is 1-2-3 and the voltage reference is on Phase 1. You need to connect it as Voltage and CT1 to your L2, CT2 to your L3 and CT3 to your L1.
The default output to emoncms is the four real powers (on L1, L2, L3 & L4, and the rms voltage.
The serial output for debugging is much more detailed. First the Voltage, then for each of the 3 (or 4) CTs you get rms current, real and apparent powers, and power factor. If you wish, you can send more details. (CT4 power will be zero unless it is enabled.
If you get negative powers on phases 2 & 3, the phase sequence is wrong and you need to exchange them.
Re: A newcomer – three phase, but it's a bit complicated
I thought that all the communications were working OK. I found the right sketch and loaded it, but haven't done any calibration. I wondered about the sequence of the phases and tried changing them but wasn't sure the result was better. Had I better get on with the calibration?
Later.....The heat pump has just started and I'm seeing positive figures on L2 and L1, but negative on L3. Switching the CTs round doesn't remove the negative, it just moves it. At the moment I'm seeing 1477 on L2, -2341 on L3 and 462 on L1.
What is the signage convention for import/export?
Re: A newcomer – three phase, but it's a bit complicated
Our convention is import is positive, since this is monitoring energy use. Robin's convention with his energy diverter is the converse, export is positive. You change the sign by flipping the c.t. on its cable, but if they're all wrong, you can flip the adapter on the AC-AC adapter instead. I shouldn't answer questions while I'm watching Countryfile and Antiques Roadshow! You're right, swapping 2 & 3 won't change the sign. Because of the way the voltage is shifted, it's fairly important to get the calibration right, so I do suggest you try to calibrate it as best you can, especially the phase.
Re: A newcomer – three phase, but it's a bit complicated
Just a thought: I wouldn't push your luck with trying to go through too many walls. While they are dry, it may be OK, but it could well be a different matter when they are wet, as you'll have a film of water that is electrically conducting and it will act as a mirror.
Re: A newcomer – three phase, but it's a bit complicated
I'm still not seeing meaningful values, and have a few questions.
I've tried the first steps in the calibration, but I'm getting a message when I load the sketch "avrdude: stk500_getsync(): not in sync: resp=0x00" Should I be concerned about this? If so what should I do about it?
Why do I need to adjust Vcal and Ical? Are these not set correctly in the library sketch?
The calibration notes read "Connect a pure resistive load (e.g. a heater) to L1 and adjust Phasecal1 to display a power factor of 1.00". Where do I display the power factor?
Presumably this is an iterative process of loading the sketch, observing the result, adjusting the values and reloading.
Thanks again for your help.
Andy
Re: A newcomer – three phase, but it's a bit complicated
"avrdude: stk500_getsync(): not in sync: resp=0x00" Should I be concerned about this? If so what should I do about it?
Indeed you should be concerned. It means you are not talking to the emonTx, and you have not loaded the sketch. Did you follow the instructions for setting up your Arduino IDE here: http://openenergymonitor.org/emon/buildingblocks/setting-up-the-arduino-... ?
(The instructions for Windows, OSX and Linux are different - which are you using?)
Vcal and Ical should be close if you are using the recommended ac adapter and current transformers, but they are still subject to component tolerances. If you have the means to do so, it would be better to at least check the values, and if necessary adjust them slightly.
You should be able to see the Power Factor on the serial monitor - that's when you have solved the connection problem of course.
Yes, adjusting the Phase calibration is iterative, but it is is fairly linear so by noting the values each time, you can get a fell for how much to change it to home in on unity.
Re: A newcomer – three phase, but it's a bit complicated
I'm on Windows 7. Yes, I did follow the instructions and I've set up the folder structure as described and installed the libraries . I can see everything in the sketchbook in Arduino IDE. Everything was OK on the communications test you described, but the error is occurring with the three phase sketch which compiles OK but comes up with the error when installing.
What do you mean by the "serial monitor"?
I should be able to check the values. I can at least compare with the readings I get on the inverters when I'm not consuming anything, and I can independently check the voltage on a multimeter. So the suggestions in the calibration process are a starting point and iterate from there?
Re: A newcomer – three phase, but it's a bit complicated
Have you successfully programmed the emonTx before? When you plugged the programmer in to the emonTx, did you match up the GND pins? (I say that because the shop programmer is component side down when plugged in to the emonTx V3.)
The Serial Monitor is reached with the magnifying glass icon in the top right corner of the Arduino IDE. That is where you see the result of the "Serial.print( ... )" statements in the sketch.
Re: A newcomer – three phase, but it's a bit complicated
That's much better. With the programmer plugged in correctly, I've loaded the sketch and I'm getting sensible results. Schoolboy error? I've even managed to calibrate the voltage correctly. Next step is to move on to current.
Re: A newcomer – three phase, but it's a bit complicated
"Schoolboy error?" - possibly. It could also be an under-developed sense of cynicism and a paucity of experience in the effects of the Law of Natural Perversity. ;-) At this point, I could launch a scathing attack on the choice of an unpolarised connector, but it seems to be an inherited problem, not one of OEM's making.
A blob of paint on the GND pin end of each connector half helps.
Unless you've got a separate accurate (better than 4%) clamp ammeter, I suspect your best way to calibrate current is going to be after you have done the phase calibration, and adjust it so that the power matches what your inverter is telling you. Bear in mind that you're calibrating the CT and the input together, so you can swap the CT and the cable, but not the CT and the input, in order to calibrate the one(s) not on the PV infeed.
Re: A newcomer – three phase, but it's a bit complicated
Yes, but I should have spotted that it could go either way round and checked which was correct.
It was easy to plug a heater into two of the phases (as the only load) and L2 (the phase with the voltage measurement) was reading 0.99 and L3 was 1.02. Is that close enough on the basis that there'll be some fluctuation, or should I be looking for bang on 1.00. I'll have to install another socket to check L1.
I don't have a clamp ammeter, so I've done a bit of calibration using the power being displayed on the inverters. They're reasonably accurate now, but it's been a very grey day today, so the current has been quite low.
Re: A newcomer – three phase, but it's a bit complicated
You could probably get closer but as the phase shifts in the transformers are dependent on the voltage (ac adapter) and the current (CTs) that's probably good enough. You'll probably keep an eye on it and compare the numbers you log with your supplier's meter readings and the generation meter, so if there's a glaring discrepancy you can do small tweaks over time to trim the calibration values. People have got to within about 1% with that method.
Are you now pretty much all set up and running hardware-wise, and now looking to set up emoncms?
Re: A newcomer – three phase, but it's a bit complicated
I've moved the CTs and emonTx from where I was testing the setup, to the incoming board. The calibration still looks OK and so I'm now measuring phase by phase import/export.
My three phase import meter was replaced about 18 months ago so should treat import/export correctly, summing the power across the phases to effectively work as if all generation and consumption is on a single phase as described in the attached document:
http://www.meteroperators.org.uk/assets/documents/Reverse%20running%20me...
In fact, the example described on p7 is similar to my set up.
So to report import/export, firstly I need to sum the power on the three phases to give total power, and then separately sum the positive and negative values over time to give me the total import and total export.
Err, how do I do that?
Re: A newcomer – three phase, but it's a bit complicated
You need to get to grips with emonCMS. First, I'm no expert, and second, the usual advice is to jump in and find out how it works for yourself. There is documentation, but - shall we say - it seems as if the development is going faster than the documentation can keep pace with.
The basic system is: You send the data and it pops up as an Input. You then add processing to that input (e.g. scale it, accumulate it) and write to a Feed. Feeds are what is stored in the database. You can then continue processing if you wish and send more intermediate results to more Feeds. The last thing you do is a Log to Feed (the value running through the calculation isn't saved until you Log to Feed). Having got the data into a Feed and into the database, you can use a Visualisation or a Dashboard (or several) to display it. The present value can appear on a dashboard as numbers or as a dial or as a graphic (or all three). Historical data appears graphically.
Plenty of dashboards are public and you can look at them for inspiration. Emoncms Showcase
So the specific answer to your summation problem is "+ input" to add the other 2 phases, then "allow positive" and "log to Feed" to show Import. You then do "allow negative" which wipes everything out, followed by three "+ input" and "allow negative" (maybe followed by "x -1") and "Log to Feed" to show Export. (It does need a little ingenuity at times!)
That's a very useful paper about meters & generation - I've noted it. Thanks.
Re: A newcomer – three phase, but it's a bit complicated
Dashboard up and running and the calculations look to be right. I'll have a chance to compare my figures with the import meter now.
Thanks for all your help.


Searching by name is a case-insensitive, inclusive search. For example, searching on serv would find any of serv, Service, Reserved, NTSERV, UserVortex, etc. The underscore character acts as a single character wildcard. The percent character acts as a multiple character wildcard.
Searching by TCP/IP address uses a very flexible search format, allowing you to separate the four octets (fields) of a TCP/IP address into specific searches. An asterisk (*) in place of any octet matches any value for that octet. Ranges are indicated by two numbers separated by a dash (-), and commas are used for list demarcation.
For example, the following search fields are all valid and would each create the same result set--all TCP/IP addresses from <IP_ADDRESS> through <IP_ADDRESS>:
A search for ifAlias, ifName, or ifDescr "contains" will find nodes with interfaces that match the given search string. This is a case-insensitive inclusive search similar to the "name" search described above. If the search modifier is "equals" rather than "contains" an exact match must be found.
To search by Service, click the down arrow and select the service you would like to search for.
Searching by MAC Address allows you to find interfaces with hardware (MAC) addresses matching the search string. This is a case-insensitive partial string match. For example, you can find all interfaces with a specified manufacturer's code by entering the first 6 characters of the mac address. Octet separators (dash or colon) are optional.
Searching for assets allows you to search for all assets which have been associated with a particular category, as well as to select a specific asset field (with all available fields listed in the drop-down list box) and search for text which matches its current value. The latter search is very similar to the text search for node names described above.
Also note that you can quickly search for all nodes which have asset information assigned by clicking the List all nodes with asset info link.


Né
Restaurants
Hotels
Music
(current)
Nilangé Stars
Nilangé Guide · The Guide to India
Music.
Without music to decorate it, time is just a bunch of boring production deadlines or dates by which bills must be paid.
Search
All time
2019
#1
Blinding Lights
The Weeknd
#1
Blinding Lights
The Weeknd


About Me
Let me tell you a few things about me
BIO
Hey Everyone! My name is Prince KABASELE, i am 23 years old and i am passionated about web technologies specifically JavaScript. I get started WebDev in 2017 and begun working as a pro in 2019. Very glad to have you on board!
AMG-PROJUSTITIA
Fullstack Developer
Consisted on building a criminal register. I have designed the UI and wrote down the technical specifications for the WebApp. We've built it within 2 months with the MERN stack.
Motorcy
UI Designer & Front-end Dev
One of my favorite self-side project, Motorcy, a fictious company that sells motorcycles. The WebApp was built as a presentation of what the company offers.
Nexter
Front-end Dev
A remote job, they sent me the design made with Figma in order to implement the Interface.


|
|
std::string | MDE::get_name () |
| |
| std::string | MDE::get_name_vMDE_by_index (int index_vMDEe) |
| | This member function is to get the standard string from the private member 'name' of a pointer to an instance of an object of class MDE, at the integer index number index_vMDEe of the private member vMDE, vector of pointers to instances of class MDE. More...
|
| |
| std::string | MDE::get_data_vMDE_by_index (int index_vMDEe) |
| | This member function is to get the standard string from the public member 'data' of a pointer to an instance of an object of class MDE, at the integer index number index_vMDEe of the private member vMDE, vector of pointers to instances of class MDE. More...
|
| |
| MDE * | MDE::vMDE_get_by_index (std::vector< int > &vect_index, std::vector< int >::const_iterator it) |
| | This member function is to return the pointer to the instance of MDE that is at a given set of indexes. More...
|
| |
Methods to get members or instances of MDE and vMDE.
| std::string MDE::get_data_vMDE_by_index |
( |
int |
index_vMDEe | ) |
|
This member function is to get the standard string from the public member 'data' of a pointer to an instance of an object of class MDE, at the integer index number index_vMDEe of the private member vMDE, vector of pointers to instances of class MDE.
- Parameters
-
| index_vMDEe | is an integer. |
- Returns
- A standard string is returned.
- See also
- set_data_vMDE_back().
-
get_name_vMDE_by_index().
-
set_name_vMDE_index().
- Exceptions
-
| std::string MDE::get_name_vMDE_by_index |
( |
int |
index_vMDEe | ) |
|
This member function is to get the standard string from the private member 'name' of a pointer to an instance of an object of class MDE, at the integer index number index_vMDEe of the private member vMDE, vector of pointers to instances of class MDE.
- Parameters
-
| index_vMDEe | is an integer. |
- Returns
- A standard string is returned.
- See also
- set_name_vMDE_index().
-
get_data_vMDE_by_index().
-
set_data_vMDE_back().
- Exceptions
-
| MDE * MDE::vMDE_get_by_index |
( |
std::vector< int > & |
vect_index, |
|
|
std::vector< int >::const_iterator |
it |
|
) |
| |
This member function is to return the pointer to the instance of MDE that is at a given set of indexes.
name: vMDE_get_by_index(std::vector<int>& vect_index,
std::vector<int>::const_iterator it)
- Parameters
-
| N | & vect_index is a reference to a vector of integer holding the indexes of the instance of MDE to return. |
| const_iterator | i is a cosntant iterator of a vector of integer, used for the recursive iteration while browsing through the called instance of MDE. |
- Returns
- MDE * : a pointer to an existing instance of MDE.
- Exceptions
-


Banka
Sign up to get access to all our
banking services.
NB: Required fields begin with
Title
Dr.
Engr.
Mr.
Mrs.
Last Name
First Name
Sex
Female
Male
Date of Birth
Email
Phone Number
Password
Confirm Password
Profile Picture
Sign Up
Already have an account?
Sign In


With more than 25 years of experience, Samudera Pacific Maju are widely known as an asset-based company with comprehensive transportation capabilities. Through the years we have maintained excellent partnerships with global shipping lines, local port administration and customs that ultimately lead us to be an established and reliable logistics service provider in Indonesia.
As a provider of full-service logistics operations, we are fully aware of the requirements of modern-day shipping. That's why we offer a wide range of services equipped with computer-based cargo tracking technology, warehousing, container depot, extensive cargo, ship chartering, cargo consolidation, international forwarding and other facilities to ensure high level of satisfaction for both our clients and business partners alike.
Experience is indeed the best teacher. We believe that in order to provide premium quality services, continuous improvement is a must. That's why we never stop to improve ourselves by learning from decades of experience in order to become Indonesia's most efficient and reliable cargo transportation company. With that vision, we carry a mission to emerge Indonesia as a global trading partner by providing quality International standards services to meet the needs of the world market.


WITNESS LIST
Government Organization
May 16, 2013 8:00 AM
FOR:
Howden, Robert (Self), Austin, TX
ON:
Bristol, George Retired (State Park Advisory Committee), Fort Worth, TX
Cornell, Dona Vice Chancellor/Vice President Legal Affairs- University of Houston
(University of Houston), Houston, TX
Farnsworth, Ward Dean (University of Texas School of Law), Austin, TX
Safadi, Randa Vice Chancellor for Exterior Relations (University of Texas System),
Austin, TX
Registering, but not testifying:
FOR:
Baggett, Donnis Executive Vice President (Texas Press Association), Austin, TX
ON:
Pigott, Ron Director of Texas Procurement and Support Services Division (Comptroller of
Public Accounts), Austin, TX
FOR:
Stoppenhagen, Dan R. Director of Transportation and Infrastructure (Fluor), Austin, TX
ON:
Pigott, Ron Director of Texas Procurement and Safety Services (Comptroller of Public
Accountants), Austin, TX


#include <target_manager.h>
Data Fields | |
| char | tid [MAX_LENOFTID] |
| target identifier | |
| char * | targetname |
| local file path or URL ( URL is suported only with SERVER mode) | |
| int | fd |
| file descriptor | |
| int | csn |
| codestream number | |
| index_param_t * | codeidx |
| index information of codestream | |
| int | num_of_use |
| numbers of sessions refering to this target | |
| OPJ_BOOL | jppstream |
| if this target can return JPP-stream | |
| OPJ_BOOL | jptstream |
| if this target can return JPP-stream | |
| target_param * | next |
| pointer to the next target |
|
|
index information of codestream
|
|
|
codestream number
|
|
|
file descriptor
|
|
|
if this target can return JPP-stream
|
|
|
if this target can return JPP-stream
|
|
|
pointer to the next target
|
|
|
numbers of sessions refering to this target
|
|
|
local file path or URL ( URL is suported only with SERVER mode)
|
|
|
target identifier
|


|
|||||||||||||||||||
| Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
| Element.java | - | - | - | - |
|
| 1 | /* | |
| 2 | * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. | |
| 3 | * | |
| 4 | * This software is open source. | |
| 5 | * See the bottom of this file for the licence. | |
| 6 | */ | |
| 7 | ||
| 8 | package org.dom4j; | |
| 9 | ||
| 10 | import java.util.Iterator; | |
| 11 | import java.util.List; | |
| 12 | import java.util.Map; | |
| 13 | ||
| 14 | /** | |
| 15 | *
 | |
| 16 | * Element interface defines an XML element. An element can have | |
| 17 | * declared namespaces, attributes, child nodes and textual content. | |
| 18 | *
 | |
| 19 | * | |
| 20 | *
 | |
| 21 | * Some of this interface is optional. Some implementations may be read-only and | |
| 22 | * not support being modified. Some implementations may not support the parent | |
| 23 | * relationship and methods such as {@link #getParent}or {@link#getDocument}. | |
| 24 | *
 | |
| 25 | * | |
| 26 | * @author <a<EMAIL_ADDRESS>Strachan  | |
| 27 | * @version $Revision: 1.47 $ | |
| 28 | */ | |
| 29 | public interface Element extends Branch { | |
| 30 | // Name and namespace related methods | |
| 31 | // ------------------------------------------------------------------------- | |
| 32 | ||
| 33 | /** | |
| 34 | *
 | |
| 35 | * Returns the QName of this element which represents the | |
| 36 | * local name, the qualified name and the Namespace. | |
| 37 | *
 | |
| 38 | * | |
| 39 | * @return the QName associated with this element | |
| 40 | */ | |
| 41 | QName getQName(); | |
| 42 | ||
| 43 | /** | |
| 44 | *
 | |
| 45 | * Sets the QName of this element which represents the local | |
| 46 | * name, the qualified name and the Namespace. | |
| 47 | *
 | |
| 48 | * | |
| 49 | * @param qname | |
| 50 | * is the QName to be associated with this element | |
| 51 | */ | |
| 52 | void setQName(QName qname); | |
| 53 | ||
| 54 | /** | |
| 55 | *
 | |
| 56 | * Returns the Namespace of this element if one exists | |
| 57 | * otherwise Namespace.NO_NAMESPACE is returned. | |
| 58 | *
 | |
| 59 | * | |
| 60 | * @return the Namespace associated with this element | |
| 61 | */ | |
| 62 | Namespace getNamespace(); | |
| 63 | ||
| 64 | /** | |
| 65 | *
 | |
| 66 | * Returns the QName for the given qualified name, using the | |
| 67 | * namespace URI in scope for the given prefix of the qualified name or the | |
| 68 | * default namespace if the qualified name has no prefix. | |
| 69 | *
 | |
| 70 | * | |
| 71 | * @param qualifiedName | |
| 72 | * DOCUMENT ME! | |
| 73 | * | |
| 74 | * @return the QName for the given qualified name | |
| 75 | */ | |
| 76 | QName getQName(String qualifiedName); | |
| 77 | ||
| 78 | /** | |
| 79 | *
 | |
| 80 | * Returns the Namespace which is mapped to the given prefix | |
| 81 | * or null if it could not be found. | |
| 82 | *
 | |
| 83 | * | |
| 84 | * @param prefix | |
| 85 | * DOCUMENT ME! | |
| 86 | * | |
| 87 | * @return the Namespace associated with the given prefix | |
| 88 | */ | |
| 89 | Namespace getNamespaceForPrefix(String prefix); | |
| 90 | ||
| 91 | /** | |
| 92 | *
 | |
| 93 | * Returns the Namespace which is mapped to the given URI or | |
| 94 | * null if it could not be found. If there is more than one | |
| 95 | * Namespace mapped to the URI, which of them will be | |
| 96 | * returned is undetermined. | |
| 97 | *
 | |
| 98 | * | |
| 99 | * @param uri | |
| 100 | * DOCUMENT ME! | |
| 101 | * | |
| 102 | * @return the Namespace associated with the given URI | |
| 103 | */ | |
| 104 | Namespace getNamespaceForURI(String uri); | |
| 105 | ||
| 106 | /** | |
| 107 | *
 | |
| 108 | * Returns the all namespaces which are mapped to the given URI or an empty | |
| 109 | * list if no such namespaces could be found. | |
| 110 | *
 | |
| 111 | * | |
| 112 | * @param uri | |
| 113 | * DOCUMENT ME! | |
| 114 | * | |
| 115 | * @return the namespaces associated with the given URI | |
| 116 | * | |
| 117 | * @since 1.5 | |
| 118 | */ | |
| 119 | List getNamespacesForURI(String uri); | |
| 120 | ||
| 121 | /** | |
| 122 | *
 | |
| 123 | * Returns the namespace prefix of this element if one exists otherwise an | |
| 124 | * empty String is returned. | |
| 125 | *
 | |
| 126 | * | |
| 127 | * @return the prefix of the Namespace of this element or an | |
| 128 | * empty String | |
| 129 | */ | |
| 130 | String getNamespacePrefix(); | |
| 131 | ||
| 132 | /** | |
| 133 | *
 | |
| 134 | * Returns the URI mapped to the namespace of this element if one exists | |
| 135 | * otherwise an empty String is returned. | |
| 136 | *
 | |
| 137 | * | |
| 138 | * @return the URI for the Namespace of this element or an | |
| 139 | * empty String | |
| 140 | */ | |
| 141 | String getNamespaceURI(); | |
| 142 | ||
| 143 | /** | |
| 144 | *
 | |
| 145 | * Returns the fully qualified name of this element. This will be the same | |
| 146 | * as the value returned from {@link #getName}if this element has no | |
| 147 | * namespace attached to this element or an expression of the form | |
| 148 | * | |
| 149 | *
 | |
| 150 | * getNamespacePrefix() + ":" + getName() | |
| 151 | *
 | |
| 152 | * | |
| 153 | * will be returned. | |
| 154 | *
 | |
| 155 | * | |
| 156 | * @return the fully qualified name of the element. | |
| 157 | */ | |
| 158 | String getQualifiedName(); | |
| 159 | ||
| 160 | /** | |
| 161 | *
 | |
| 162 | * Returns any additional namespaces declarations for this element other | |
| 163 | * than namespace returned via the {@link #getNamespace()}method. If no | |
| 164 | * additional namespace declarations are present for this element then an | |
| 165 | * empty list will be returned. The list is backed by the element such that | |
| 166 | * changes to the list will be reflected in the element though the reverse | |
| 167 | * is not the case. | |
| 168 | *
 | |
| 169 | * | |
| 170 | * @return a list of any additional namespace declarations. | |
| 171 | */ | |
| 172 | List additionalNamespaces(); | |
| 173 | ||
| 174 | /** | |
| 175 | *
 | |
| 176 | * Returns all the namespaces declared by this element. If no namespaces are | |
| 177 | * declared for this element then an empty list will be returned. The list | |
| 178 | * is backed by the element such that changes to the list will be reflected | |
| 179 | * in the element though the reverse is not the case. | |
| 180 | *
 | |
| 181 | * | |
| 182 | * @return a list of namespaces declared for this element. | |
| 183 | */ | |
| 184 | List declaredNamespaces(); | |
| 185 | ||
| 186 | // Builder methods | |
| 187 | // ------------------------------------------------------------------------- | |
| 188 | ||
| 189 | /** | |
| 190 | *
 | |
| 191 | * Adds the attribute value of the given local name. If an attribute already | |
| 192 | * exists for the given name it will be replaced. Attributes with null | |
| 193 | * values are silently ignored. If the value of the attribute is null then | |
| 194 | * this method call will remove any attributes with the given name. | |
| 195 | *
 | |
| 196 | * | |
| 197 | * @param name | |
| 198 | * is the name of the attribute whose value is to be added or | |
| 199 | * updated | |
| 200 | * @param value | |
| 201 | * is the attribute's value | |
| 202 | * | |
| 203 | * @return this Element instance. | |
| 204 | */ | |
| 205 | Element addAttribute(String name, String value); | |
| 206 | ||
| 207 | /** | |
| 208 | *
 | |
| 209 | * Adds the attribute value of the given fully qualified name. If an | |
| 210 | * attribute already exists for the given name it will be replaced. | |
| 211 | * Attributes with null values are silently ignored. If the value of the | |
| 212 | * attribute is null then this method call will remove any attributes with | |
| 213 | * the given name. | |
| 214 | *
 | |
| 215 | * | |
| 216 | * @param qName | |
| 217 | * is the fully qualified name of the attribute whose value is to | |
| 218 | * be added or updated | |
| 219 | * @param value | |
| 220 | * is the attribute's value | |
| 221 | * | |
| 222 | * @return this Element instance. | |
| 223 | */ | |
| 224 | Element addAttribute(QName qName, String value); | |
| 225 | ||
| 226 | /** | |
| 227 | * Adds a new Comment node with the given text to this | |
| 228 | * element. | |
| 229 | * | |
| 230 | * @param comment | |
| 231 | * is the text for the Comment node. | |
| 232 | * | |
| 233 | * @return this Element instance. | |
| 234 | */ | |
| 235 | Element addComment(String comment); | |
| 236 | ||
| 237 | /** | |
| 238 | * Adds a new CDATA node with the given text to this element. | |
| 239 | * | |
| 240 | * @param cdata | |
| 241 | * is the text for the CDATA node. | |
| 242 | * | |
| 243 | * @return this Element instance. | |
| 244 | */ | |
| 245 | Element addCDATA(String cdata); | |
| 246 | ||
| 247 | /** | |
| 248 | * Adds a new Entity node with the given name and text to | |
| 249 | * this element and returns a reference to the new node. | |
| 250 | * | |
| 251 | * @param name | |
| 252 | * is the name for the Entity node. | |
| 253 | * @param text | |
| 254 | * is the text for the Entity node. | |
| 255 | * | |
| 256 | * @return this Element instance. | |
| 257 | */ | |
| 258 | Element addEntity(String name, String text); | |
| 259 | ||
| 260 | /** | |
| 261 | * Adds a namespace to this element for use by its child content | |
| 262 | * | |
| 263 | * @param prefix | |
| 264 | * is the prefix to use, which should not be null or blank | |
| 265 | * @param uri | |
| 266 | * is the namespace URI | |
| 267 | * | |
| 268 | * @return this Element instance. | |
| 269 | */ | |
| 270 | Element addNamespace(String prefix, String uri); | |
| 271 | ||
| 272 | /** | |
| 273 | * Adds a processing instruction for the given target | |
| 274 | * | |
| 275 | * @param target | |
| 276 | * is the target of the processing instruction | |
| 277 | * @param text | |
| 278 | * is the textual data (key/value pairs) of the processing | |
| 279 | * instruction | |
| 280 | * | |
| 281 | * @return this Element instance. | |
| 282 | */ | |
| 283 | Element addProcessingInstruction(String target, String text); | |
| 284 | ||
| 285 | /** | |
| 286 | * Adds a processing instruction for the given target | |
| 287 | * | |
| 288 | * @param target | |
| 289 | * is the target of the processing instruction | |
| 290 | * @param data | |
| 291 | * is a Map of the key / value pairs of the processing | |
| 292 | * instruction | |
| 293 | * | |
| 294 | * @return this Element instance. | |
| 295 | */ | |
| 296 | Element addProcessingInstruction(String target, Map data); | |
| 297 | ||
| 298 | /** | |
| 299 | * Adds a new Text node with the given text to this element. | |
| 300 | * | |
| 301 | * @param text | |
| 302 | * is the text for the Text node. | |
| 303 | * | |
| 304 | * @return this Element instance. | |
| 305 | */ | |
| 306 | Element addText(String text); | |
| 307 | ||
| 308 | // Typesafe modifying methods | |
| 309 | // ------------------------------------------------------------------------- | |
| 310 | ||
| 311 | /** | |
| 312 | * Adds the given Attribute to this element. If the given | |
| 313 | * node already has a parent defined then an | |
| 314 | * IllegalAddException will be thrown. Attributes with null | |
| 315 | * values are silently ignored. | |
| 316 | * | |
| 317 | *
 | |
| 318 | * If the value of the attribute is null then this method call will remove | |
| 319 | * any attributes with the QName of this attribute. | |
| 320 | *
 | |
| 321 | * | |
| 322 | * @param attribute | |
| 323 | * is the attribute to be added | |
| 324 | */ | |
| 325 | void add(Attribute attribute); | |
| 326 | ||
| 327 | /** | |
| 328 | * Adds the given CDATA to this element. If the given node | |
| 329 | * already has a parent defined then an IllegalAddException | |
| 330 | * will be thrown. | |
| 331 | * | |
| 332 | * @param cdata | |
| 333 | * is the CDATA to be added | |
| 334 | */ | |
| 335 | void add(CDATA cdata); | |
| 336 | ||
| 337 | /** | |
| 338 | * Adds the given Entity to this element. If the given node | |
| 339 | * already has a parent defined then an IllegalAddException | |
| 340 | * will be thrown. | |
| 341 | * | |
| 342 | * @param entity | |
| 343 | * is the entity to be added | |
| 344 | */ | |
| 345 | void add(Entity entity); | |
| 346 | ||
| 347 | /** | |
| 348 | * Adds the given Text to this element. If the given node | |
| 349 | * already has a parent defined then an IllegalAddException | |
| 350 | * will be thrown. | |
| 351 | * | |
| 352 | * @param text | |
| 353 | * is the text to be added | |
| 354 | */ | |
| 355 | void add(Text text); | |
| 356 | ||
| 357 | /** | |
| 358 | * Adds the given Namespace to this element. If the given | |
| 359 | * node already has a parent defined then an | |
| 360 | * IllegalAddException will be thrown. | |
| 361 | * | |
| 362 | * @param namespace | |
| 363 | * is the namespace to be added | |
| 364 | */ | |
| 365 | void add(Namespace namespace); | |
| 366 | ||
| 367 | /** | |
| 368 | * Removes the given Attribute from this element. | |
| 369 | * | |
| 370 | * @param attribute | |
| 371 | * is the attribute to be removed | |
| 372 | * | |
| 373 | * @return true if the attribute was removed | |
| 374 | */ | |
| 375 | boolean remove(Attribute attribute); | |
| 376 | ||
| 377 | /** | |
| 378 | * Removes the given CDATA if the node is an immediate child | |
| 379 | * of this element. If the given node is not an immediate child of this | |
| 380 | * element then the {@link Node#detach()}method should be used instead. | |
| 381 | * | |
| 382 | * @param cdata | |
| 383 | * is the CDATA to be removed | |
| 384 | * | |
| 385 | * @return true if the cdata was removed | |
| 386 | */ | |
| 387 | boolean remove(CDATA cdata); | |
| 388 | ||
| 389 | /** | |
| 390 | * Removes the given Entity if the node is an immediate child | |
| 391 | * of this element. If the given node is not an immediate child of this | |
| 392 | * element then the {@link Node#detach()}method should be used instead. | |
| 393 | * | |
| 394 | * @param entity | |
| 395 | * is the entity to be removed | |
| 396 | * | |
| 397 | * @return true if the entity was removed | |
| 398 | */ | |
| 399 | boolean remove(Entity entity); | |
| 400 | ||
| 401 | /** | |
| 402 | * Removes the given Namespace if the node is an immediate | |
| 403 | * child of this element. If the given node is not an immediate child of | |
| 404 | * this element then the {@link Node#detach()}method should be used | |
| 405 | * instead. | |
| 406 | * | |
| 407 | * @param namespace | |
| 408 | * is the namespace to be removed | |
| 409 | * | |
| 410 | * @return true if the namespace was removed | |
| 411 | */ | |
| 412 | boolean remove(Namespace namespace); | |
| 413 | ||
| 414 | /** | |
| 415 | * Removes the given Text if the node is an immediate child | |
| 416 | * of this element. If the given node is not an immediate child of this | |
| 417 | * element then the {@link Node#detach()}method should be used instead. | |
| 418 | * | |
| 419 | * @param text | |
| 420 | * is the text to be removed | |
| 421 | * | |
| 422 | * @return true if the text was removed | |
| 423 | */ | |
| 424 | boolean remove(Text text); | |
| 425 | ||
| 426 | // Text methods | |
| 427 | // ------------------------------------------------------------------------- | |
| 428 | ||
| 429 | /** | |
| 430 | * Returns the text value of this element without recursing through child | |
| 431 | * elements. This method iterates through all {@link Text},{@link CDATA} | |
| 432 | * and {@link Entity}nodes that this element contains and appends the text | |
| 433 | * values together. | |
| 434 | * | |
| 435 | * @return the textual content of this Element. Child elements are not | |
| 436 | * navigated. This method does not return null; | |
| 437 | */ | |
| 438 | String getText(); | |
| 439 | ||
| 440 | /** | |
| 441 | * DOCUMENT ME! | |
| 442 | * | |
| 443 | * @return the trimmed text value where whitespace is trimmed and normalised | |
| 444 | * into single spaces. This method does not return null. | |
| 445 | */ | |
| 446 | String getTextTrim(); | |
| 447 | ||
| 448 | /** | |
| 449 | * Returns the XPath string-value of this node. The behaviour of this method | |
| 450 | * is defined in the XPath | |
| 451 | * specification . This method returns the string-value of all the | |
| 452 | * contained {@link Text},{@link CDATA},{@link Entity}and {@link | |
| 453 | * Element} nodes all appended together. | |
| 454 | * | |
| 455 | * @return the text from all the child Text and Element nodes appended | |
| 456 | * together. | |
| 457 | */ | |
| 458 | String getStringValue(); | |
| 459 | ||
| 460 | /** | |
| 461 | * Accesses the data of this element which may implement data typing | |
| 462 | * bindings such as XML Schema or Java Bean bindings or will return the same | |
| 463 | * value as {@link #getText} | |
| 464 | * | |
| 465 | * @return DOCUMENT ME! | |
| 466 | */ | |
| 467 | Object getData(); | |
| 468 | ||
| 469 | /** | |
| 470 | * Sets the data value of this element if this element supports data binding | |
| 471 | * or calls {@link #setText}if it doesn't | |
| 472 | * | |
| 473 | * @param data | |
| 474 | * DOCUMENT ME! | |
| 475 | */ | |
| 476 | void setData(Object data); | |
| 477 | ||
| 478 | // Attribute methods | |
| 479 | // ------------------------------------------------------------------------- | |
| 480 | ||
| 481 | /** | |
| 482 | *
 | |
| 483 | * Returns the {@link Attribute}instances this element contains as a backed | |
| 484 | * {@link List}so that the attributes may be modified directly using the | |
| 485 | * {@link List}interface. The List is backed by the | |
| 486 | * Element so that changes to the list are reflected in the | |
| 487 | * element and vice versa. | |
| 488 | *
 | |
| 489 | * | |
| 490 | * @return the attributes that this element contains as a List | |
| 491 | */ | |
| 492 | List attributes(); | |
| 493 | ||
| 494 | /** | |
| 495 | * Sets the attributes that this element contains | |
| 496 | * | |
| 497 | * @param attributes | |
| 498 | * DOCUMENT ME! | |
| 499 | */ | |
| 500 | void setAttributes(List attributes); | |
| 501 | ||
| 502 | /** | |
| 503 | * DOCUMENT ME! | |
| 504 | * | |
| 505 | * @return the number of attributes this element contains | |
| 506 | */ | |
| 507 | int attributeCount(); | |
| 508 | ||
| 509 | /** | |
| 510 | * DOCUMENT ME! | |
| 511 | * | |
| 512 | * @return an iterator over the attributes of this element | |
| 513 | */ | |
| 514 | Iterator attributeIterator(); | |
| 515 | ||
| 516 | /** | |
| 517 | * Returns the attribute at the specified indexGets the | |
| 518 | * | |
| 519 | * @param index | |
| 520 | * DOCUMENT ME! | |
| 521 | * | |
| 522 | * @return the attribute at the specified index where index >= 0 and | |
| 523 | * index < number of attributes or throws an | |
| 524 | * IndexOutOfBoundsException if the index is not within the | |
| 525 | * allowable range | |
| 526 | */ | |
| 527 | Attribute attribute(int index); | |
| 528 | ||
| 529 | /** | |
| 530 | * Returns the attribute with the given name | |
| 531 | * | |
| 532 | * @param name | |
| 533 | * DOCUMENT ME! | |
| 534 | * | |
| 535 | * @return the attribute for the given local name in any namespace. If there | |
| 536 | * are more than one attributes with the given local name in | |
| 537 | * different namespaces then the first one is returned. | |
| 538 | */ | |
| 539 | Attribute attribute(String name); | |
| 540 | ||
| 541 | /** | |
| 542 | * DOCUMENT ME! | |
| 543 | * | |
| 544 | * @param qName | |
| 545 | * is the fully qualified name | |
| 546 | * | |
| 547 | * @return the attribute for the given fully qualified name or null if it | |
| 548 | * could not be found. | |
| 549 | */ | |
| 550 | Attribute attribute(QName qName); | |
| 551 | ||
| 552 | /** | |
| 553 | *
 | |
| 554 | * This returns the attribute value for the attribute with the given name | |
| 555 | * and any namespace or null if there is no such attribute or the empty | |
| 556 | * string if the attribute value is empty. | |
| 557 | *
 | |
| 558 | * | |
| 559 | * @param name | |
| 560 | * is the name of the attribute value to be returnd | |
| 561 | * | |
| 562 | * @return the value of the attribute, null if the attribute does not exist | |
| 563 | * or the empty string | |
| 564 | */ | |
| 565 | String attributeValue(String name); | |
| 566 | ||
| 567 | /** | |
| 568 | *
 | |
| 569 | * This returns the attribute value for the attribute with the given name | |
| 570 | * and any namespace or the default value if there is no such attribute | |
| 571 | * value. | |
| 572 | *
 | |
| 573 | * | |
| 574 | * @param name | |
| 575 | * is the name of the attribute value to be returnd | |
| 576 | * @param defaultValue | |
| 577 | * is the default value to be returned if the attribute has no | |
| 578 | * value defined. | |
| 579 | * | |
| 580 | * @return the value of the attribute or the defaultValue if the attribute | |
| 581 | * has no value defined. | |
| 582 | */ | |
| 583 | String attributeValue(String name, String defaultValue); | |
| 584 | ||
| 585 | /** | |
| 586 | *
 | |
| 587 | * This returns the attribute value for the attribute with the given fully | |
| 588 | * qualified name or null if there is no such attribute or the empty string | |
| 589 | * if the attribute value is empty. | |
| 590 | *
 | |
| 591 | * | |
| 592 | * @param qName | |
| 593 | * is the fully qualified name | |
| 594 | * | |
| 595 | * @return the value of the attribute, null if the attribute does not exist | |
| 596 | * or the empty string | |
| 597 | */ | |
| 598 | String attributeValue(QName qName); | |
| 599 | ||
| 600 | /** | |
| 601 | *
 | |
| 602 | * This returns the attribute value for the attribute with the given fully | |
| 603 | * qualified name or the default value if there is no such attribute value. | |
| 604 | *
 | |
| 605 | * | |
| 606 | * @param qName | |
| 607 | * is the fully qualified name | |
| 608 | * @param defaultValue | |
| 609 | * is the default value to be returned if the attribute has no | |
| 610 | * value defined. | |
| 611 | * | |
| 612 | * @return the value of the attribute or the defaultValue if the attribute | |
| 613 | * has no value defined. | |
| 614 | */ | |
| 615 | String attributeValue(QName qName, String defaultValue); | |
| 616 | ||
| 617 | /** | |
| 618 | *
 | |
| 619 | * Sets the attribute value of the given local name. | |
| 620 | *
 | |
| 621 | * | |
| 622 | * @param name | |
| 623 | * is the name of the attribute whose value is to be added or | |
| 624 | * updated | |
| 625 | * @param value | |
| 626 | * is the attribute's value | |
| 627 | * | |
| 628 | * @deprecated As of version 0.5. Please use {@link | |
| 629 | * #addAttribute(String,String)} instead. WILL BE REMOVED IN | |
| 630 | * dom4j-1.6 !! | |
| 631 | */ | |
| 632 | void setAttributeValue(String name, String value); | |
| 633 | ||
| 634 | /** | |
| 635 | *
 | |
| 636 | * Sets the attribute value of the given fully qualified name. | |
| 637 | *
 | |
| 638 | * | |
| 639 | * @param qName | |
| 640 | * is the fully qualified name of the attribute whose value is to | |
| 641 | * be added or updated | |
| 642 | * @param value | |
| 643 | * is the attribute's value | |
| 644 | * | |
| 645 | * @deprecated As of version 0.5. Please use {@link | |
| 646 | * #addAttribute(QName,String)} instead. WILL BE REMOVED IN | |
| 647 | * dom4j-1.6 !! | |
| 648 | */ | |
| 649 | void setAttributeValue(QName qName, String value); | |
| 650 | ||
| 651 | // Content methods | |
| 652 | // ------------------------------------------------------------------------- | |
| 653 | ||
| 654 | /** | |
| 655 | * Returns the first element for the given local name and any namespace. | |
| 656 | * | |
| 657 | * @param name | |
| 658 | * DOCUMENT ME! | |
| 659 | * | |
| 660 | * @return the first element with the given local name | |
| 661 | */ | |
| 662 | Element element(String name); | |
| 663 | ||
| 664 | /** | |
| 665 | * Returns the first element for the given fully qualified name. | |
| 666 | * | |
| 667 | * @param qName | |
| 668 | * is the fully qualified name to search for | |
| 669 | * | |
| 670 | * @return the first element with the given fully qualified name | |
| 671 | */ | |
| 672 | Element element(QName qName); | |
| 673 | ||
| 674 | /** | |
| 675 | *
 | |
| 676 | * Returns the elements contained in this element. If this element does not | |
| 677 | * contain any elements then this method returns an empty list. The list is | |
| 678 | * backed by the element such that changes to the list will be reflected in | |
| 679 | * the element though the reverse is not the case. | |
| 680 | *
 | |
| 681 | * | |
| 682 | * @return a list of all the elements in this element. | |
| 683 | */ | |
| 684 | List elements(); | |
| 685 | ||
| 686 | /** | |
| 687 | *
 | |
| 688 | * Returns the elements contained in this element with the given local name | |
| 689 | * and any namespace. If no elements are found then this method returns an | |
| 690 | * empty list. The list is backed by the element such that changes to the | |
| 691 | * list will be reflected in the element though the reverse is not the case. | |
| 692 | *
 | |
| 693 | * | |
| 694 | * @param name | |
| 695 | * DOCUMENT ME! | |
| 696 | * | |
| 697 | * @return a list of all the elements in this element for the given local | |
| 698 | * name | |
| 699 | */ | |
| 700 | List elements(String name); | |
| 701 | ||
| 702 | /** | |
| 703 | *
 | |
| 704 | * Returns the elements contained in this element with the given fully | |
| 705 | * qualified name. If no elements are found then this method returns an | |
| 706 | * empty list. The list is backed by the element such that changes to the | |
| 707 | * list will be reflected in the element though the reverse is not the case. | |
| 708 | *
 | |
| 709 | * | |
| 710 | * @param qName | |
| 711 | * is the fully qualified name to search for | |
| 712 | * | |
| 713 | * @return a list of all the elements in this element for the given fully | |
| 714 | * qualified name. | |
| 715 | */ | |
| 716 | List elements(QName qName); | |
| 717 | ||
| 718 | /** | |
| 719 | * Returns an iterator over all this elements child elements. | |
| 720 | * | |
| 721 | * @return an iterator over the contained elements | |
| 722 | */ | |
| 723 | Iterator elementIterator(); | |
| 724 | ||
| 725 | /** | |
| 726 | * Returns an iterator over the elements contained in this element which | |
| 727 | * match the given local name and any namespace. | |
| 728 | * | |
| 729 | * @param name | |
| 730 | * DOCUMENT ME! | |
| 731 | * | |
| 732 | * @return an iterator over the contained elements matching the given local | |
| 733 | * name | |
| 734 | */ | |
| 735 | Iterator elementIterator(String name); | |
| 736 | ||
| 737 | /** | |
| 738 | * Returns an iterator over the elements contained in this element which | |
| 739 | * match the given fully qualified name. | |
| 740 | * | |
| 741 | * @param qName | |
| 742 | * is the fully qualified name to search for | |
| 743 | * | |
| 744 | * @return an iterator over the contained elements matching the given fully | |
| 745 | * qualified name | |
| 746 | */ | |
| 747 | Iterator elementIterator(QName qName); | |
| 748 | ||
| 749 | // Helper methods | |
| 750 | // ------------------------------------------------------------------------- | |
| 751 | ||
| 752 | /** | |
| 753 | * DOCUMENT ME! | |
| 754 | * | |
| 755 | * @return true if this element is the root element of a document and this | |
| 756 | * element supports the parent relationship else false. | |
| 757 | */ | |
| 758 | boolean isRootElement(); | |
| 759 | ||
| 760 | /** | |
| 761 | *
 | |
| 762 | * Returns true if this Element has mixed content. Mixed | |
| 763 | * content means that an element contains both textual data and child | |
| 764 | * elements. | |
| 765 | *
 | |
| 766 | * | |
| 767 | * @return true if this element contains mixed content. | |
| 768 | */ | |
| 769 | boolean hasMixedContent(); | |
| 770 | ||
| 771 | /** | |
| 772 | *
 | |
| 773 | * Returns true if this Element has text only content. | |
| 774 | *
 | |
| 775 | * | |
| 776 | * @return true if this element is empty or only contains text content. | |
| 777 | */ | |
| 778 | boolean isTextOnly(); | |
| 779 | ||
| 780 | /** | |
| 781 | * Appends the attributes of the given element to me. This method behaves | |
| 782 | * like the {@link java.util.Collection#addAll(java.util.Collection)} | |
| 783 | * method. | |
| 784 | * | |
| 785 | * @param element | |
| 786 | * is the element whose attributes will be added to me. | |
| 787 | */ | |
| 788 | void appendAttributes(Element element); | |
| 789 | ||
| 790 | /** | |
| 791 | *
 | |
| 792 | * Creates a deep copy of this element The new element is detached from its | |
| 793 | * parent, and getParent() on the clone will return null. | |
| 794 | *
 | |
| 795 | * | |
| 796 | * @return a new deep copy Element | |
| 797 | */ | |
| 798 | Element createCopy(); | |
| 799 | ||
| 800 | /** | |
| 801 | *
 | |
| 802 | * Creates a deep copy of this element with the given local name The new | |
| 803 | * element is detached from its parent, and getParent() on the clone will | |
| 804 | * return null. | |
| 805 | *
 | |
| 806 | * | |
| 807 | * @param name | |
| 808 | * DOCUMENT ME! | |
| 809 | * | |
| 810 | * @return a new deep copy Element | |
| 811 | */ | |
| 812 | Element createCopy(String name); | |
| 813 | ||
| 814 | /** | |
| 815 | *
 | |
| 816 | * Creates a deep copy of this element with the given fully qualified name. | |
| 817 | * The new element is detached from its parent, and getParent() on the clone | |
| 818 | * will return null. | |
| 819 | *
 | |
| 820 | * | |
| 821 | * @param qName | |
| 822 | * DOCUMENT ME! | |
| 823 | * | |
| 824 | * @return a new deep copy Element | |
| 825 | */ | |
| 826 | Element createCopy(QName qName); | |
| 827 | ||
| 828 | String elementText(String name); | |
| 829 | ||
| 830 | String elementText(QName qname); | |
| 831 | ||
| 832 | String elementTextTrim(String name); | |
| 833 | ||
| 834 | String elementTextTrim(QName qname); | |
| 835 | ||
| 836 | /** | |
| 837 | * Returns a node at the given index suitable for an XPath result set. This | |
| 838 | * means the resulting Node will either be null or it will support the | |
| 839 | * parent relationship. | |
| 840 | * | |
| 841 | * @param index | |
| 842 | * DOCUMENT ME! | |
| 843 | * | |
| 844 | * @return the Node for the given index which will support the parent | |
| 845 | * relationship or null if there is not a node at the given index. | |
| 846 | */ | |
| 847 | Node getXPathResult(int index); | |
| 848 | } | |
| 849 | ||
| 850 | /* | |
| 851 | * Redistribution and use of this software and associated documentation | |
| 852 | * ("Software"), with or without modification, are permitted provided that the | |
| 853 | * following conditions are met: | |
| 854 | * | |
| 855 | * 1. Redistributions of source code must retain copyright statements and | |
| 856 | * notices. Redistributions must also contain a copy of this document. | |
| 857 | * | |
| 858 | * 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 859 | * this list of conditions and the following disclaimer in the documentation | |
| 860 | * and/or other materials provided with the distribution. | |
| 861 | * | |
| 862 | * 3. The name "DOM4J" must not be used to endorse or promote products derived | |
| 863 | * from this Software without prior written permission of MetaStuff, Ltd. For | |
| 864 | * written permission, please contact<EMAIL_ADDRESS>| |
| 865 | * | |
| 866 | * 4. Products derived from this Software may not be called "DOM4J" nor may | |
| 867 | * "DOM4J" appear in their names without prior written permission of MetaStuff, | |
| 868 | * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. | |
| 869 | * | |
| 870 | * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org | |
| 871 | * | |
| 872 | * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND | |
| 873 | * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 874 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 875 | * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE | |
| 876 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
| 877 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
| 878 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
| 879 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
| 880 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
| 881 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| 882 | * POSSIBILITY OF SUCH DAMAGE. | |
| 883 | * | |
| 884 | * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. | |
| 885 | */ |
|


A cross-functional team is a group of people with different functional expertise working toward a common goal. Team members must have all of the skills necessary to create an increment of work.
Direction and Specialization
Understanding of direction is essential for this type of teams
The specialization will allow growing expertise in a particular field
Size of the team:
Product owner
Works with the stakeholders(or users) to get the right requirements, right in the senses
Creates a vision so that the development team visualize the expected outcome by the user


In multi-party video calls, attendees can enable the simulcast feature to enhance the overall video quality. Simulcast is a standardized technique where the video publishers create multiple renditions, or layers, of the same video source and video subscribers have the flexibility to choose the rendition that best fits their needs based on such factors as available bandwidth, compute and screen size.
The uplink policy controls the configuration of the renditions through camera capture and encoding parameters. The simulcast-enabled uplink policy is SimulcastUplinkPolicy.
Simulcast support is built into the WebRTC library in the majority of browsers. The video input resolution is used to initially configure the attributes and maximum number of allowed simulcast streams. In WebRTC, if the RTCRtpSender is configured to have three layers of encoding, then the top layer is specified by the video input resolution. The resolution of the middle layer is scaled down by two vertically and horizontally by WebRTC. The lower layer is scaled down by four. The WebRTC library supports a maximum of three simulcast layers, and only when the input resolution is 960x540 or higher will all three be available.
The recommended resolution in JS SDK is 1280x720. This resolution will provide the most flexibility and allow subscribers to maintain smoother video quality transitions. In certain circumstances, like mobile browsers, the input resolution may not be high enough to support all desired simulcast streams, so the logic will adapt appropriately to send as many as possible.
The SimulcastUplinkPolicy configures RTCRtpSender to have three encoding layers, but only ever enables two of them. Which two are enabled is based on a variety of factors. Experiments show that configuring RTCRtpSender with three encoding layers up front and dynamically enabling and disabling layers provides a better experience and reduces the burden of having to dynamically manage capture resolution and encoding parameters.
WebRTC ultimately controls how much data is being sent to the network based on its bandwidth estimation algorithm. It's very hard to circumvent the estimated bandwidth or trick WebRTC into sending more than it estimates. Most browsers expose WebRTC peer connection statistics which developers can access to retrieve the estimated available bandwidths for uplink or downlink.
The estimated available bandwidth reveals some information of the health of the E2E network and can trigger various WebRTC behaviors when facing network adversity or in recovering from a network glitch. SimulcastUplinkPolicy does its best to anticipate and react to the underlying WebRTC behavior and work with it to avoid further impact on the video quality of services.
The SimulcastUplinkPolicy implements the following logic:
Publishers/Attendees
Estimated Uplink Bandwidth
Simulcast stream 1
Simulcast stream 2
Attendees <= 2
Any
1280x720@15fps 1200 kbps
Not used
Publishers <= 4 and
>= 1000 kbps
1280x720@15fps 1200 kbps
320x180@15fps 300 kbps
Publishers <= 6 and
>= 350 kbps
640x360@15fps 600 kbps
320x180@15fps 200 kbps
Publishers <= 6 and
> 300 kbps
640x360@15fps 600 kbps
320x180@15fps 150 kbps
Publishers > 6 and
>= 350 kbps
640x360@15fps 350 kbps
320x180@15fps 200 kbps
Publishers > 6 and
>= 300 kbps
640x360@15fps 350 kbps
320x180@15fps 150 kbps
Any number publishers
< 300 kbps
Not used
320x180@15fps 300 kbps
The table entries represent the maximum configuration. When CPU and bandwidth consumption is overused, WebRTC will dynamically adjust bitrate, disable a layer or scale down resolution. The SimulcastUplinkPolicy has a monitoring mechanism which tracks the sending status and automatically adjusts without need for application intervention.
The VideoAdaptiveProbePolicy adds functionality to take advantage of video simulcast. The goal of this policy is to leave the complexity of managing the downlink bandwidth and decision of which streams to request inside the SDK and remove that burden from the application. The policy monitors numerous pieces of information and uses that to determine which streams to subscribe to. The data considered are:
Message from infrastructure enumerating video streams from each remote client
Estimated downlink bandwidth from WebRTC library
Media metrics such as packet loss and used bandwidth
Stream type - Screen share or camera device
The policy works by listening to any changes in the information listed above. Anytime there is a change it re-evaluates the best mix of remote videos to fit within the target downlink bandwidth. The policy is currently configured to try to request as many remote clients as possible, then increase resolution where possible. It prioritizes screen share video above people video. If there is insufficient bandwidth to request all far participants then only a certain number will be seen.
If the application pauses a remote video by calling pauseVideoTile, then this policy will not include that remote video in the list of available streams and therefore will not automatically subscribe or unsubscribe from it while it is in the paused state.
import {
ConsoleLogger,
DefaultDeviceController,
DefaultMeetingSession,
LogLevel,
MeetingSessionConfiguration
} from'amazon-chime-sdk-js';
const logger = new ConsoleLogger('MyLogger', LogLevel.INFO);
const deviceController = new DefaultDeviceController(logger);
// You need responses from server-side Chime API. See 'Getting responses from your server application' in the README.const meetingResponse = // The response from the CreateMeeting API action.const attendeeResponse = // The response from the CreateAttendee or BatchCreateAttendee API action.// This meeting session configuration will be used to enable simulcast in the next step.const configuration = new MeetingSessionConfiguration(meetingResponse, attendeeResponse);
Now you have to enable enableUnifiedPlanForChromiumBasedBrowsers and enableSimulcastForUnifiedPlanChromiumBasedBrowsers feature flags
in the created MeetingSessionConfiguration.
Now create a meeting session with the simulcast enabled meeting session configuration.
// In the examples below, you will use this meetingSession object.const meetingSession = new DefaultMeetingSession(
configuration,
logger,
deviceController
);
This meetingSession is now simulcast enabled and will have the videoUplinkBandwidthPolicy set to DefaultSimulcastUplinkPolicy and videoDownlinkBandwidthPolicy set to VideoAdaptiveProbePolicy. Due to these policies, the local and remote video resolutions may change. The video resolution depends on the available simulcast streams. The available simlucast streams are dependent on the number of attendees and the current bandwidth estimations. Check "Simulcast resolutions and behavior" section in this guide for more information.
The active simulcast streams are represented by the SimulcastLayers enum. Currently, the active upstream simulcast layers will only be either "Low and High", or "Low and Medium" or "Low". To receive upstream simulcast layer change notification do the following steps:
Then, add an instance of the AudioVideoObserver using the addObserver method so you can receive the changed simulcast layer notification.
Now when you are in a simulcast enabled meeting and your upstream simulcast layer is changed, you will be notified in the encodingSimulcastLayersDidChange callback with the updated simulcast layer.
import { SimulcastLayers } from'amazon-chime-sdk-js';
const SimulcastLayersMapping = {
[SimulcastLayers.Low]: 'Low',
[SimulcastLayers.LowAndMedium]: 'Low and Medium',
[SimulcastLayers.LowAndHigh]: 'Low and High',
[SimulcastLayers.Medium]: 'Medium',
[SimulcastLayers.MediumAndHigh]: 'Medium and High',
[SimulcastLayers.High]: 'High'
};
const observer = {
encodingSimulcastLayersDidChange: simulcastLayers => {
console.log(`current active simulcast layers changed to: ${SimulcastLayersMapping[simulcastLayers]}`);
}
}
meetingSession.audioVideo.addObserver(observer);
Video Simulcast
In multi-party video calls, attendees can enable the simulcast feature to enhance the overall video quality. Simulcast is a standardized technique where the video publishers create multiple renditions, or layers, of the same video source and video subscribers have the flexibility to choose the rendition that best fits their needs based on such factors as available bandwidth, compute and screen size. The uplink policy controls the configuration of the renditions through camera capture and encoding parameters. The simulcast-enabled uplink policy is SimulcastUplinkPolicy.
Simulcast is currently disabled by default. To enable it MeetingSessionConfiguration.enableUnifiedPlanForChromiumBasedBrowsers and MeetingSessionConfiguration.enableSimulcastForUnifiedPlanChromiumBasedBrowsers must both be set. With those set to true, the simulcast uplink policy will be automatically selected. We currently do not allow overriding the uplink policy when enable simulcast is set to true. Currently, only Chrome 76 and above is supported.
The VideoAdaptiveProbePolicy downlink policy adaptively subscribes to the best simulcast layer and is automatically selected if MeetingSessionConfiguration.enableUnifiedPlanForChromiumBasedBrowsers and MeetingSessionConfiguration.enableSimulcastForUnifiedPlanChromiumBasedBrowsers are set to true.
Details
Simulcast overview
Simulcast support is built into the WebRTC library in the majority of browsers. The video input resolution is used to initially configure the attributes and maximum number of allowed simulcast streams. In WebRTC, if the RTCRtpSender is configured to have three layers of encoding, then the top layer is specified by the video input resolution. The resolution of the middle layer is scaled down by two vertically and horizontally by WebRTC. The lower layer is scaled down by four. The WebRTC library supports a maximum of three simulcast layers, and only when the input resolution is 960x540 or higher will all three be available.
The recommended resolution in JS SDK is 1280x720. This resolution will provide the most flexibility and allow subscribers to maintain smoother video quality transitions. In certain circumstances, like mobile browsers, the input resolution may not be high enough to support all desired simulcast streams, so the logic will adapt appropriately to send as many as possible.
The SimulcastUplinkPolicy configures RTCRtpSender to have three encoding layers, but only ever enables two of them. Which two are enabled is based on a variety of factors. Experiments show that configuring RTCRtpSender with three encoding layers up front and dynamically enabling and disabling layers provides a better experience and reduces the burden of having to dynamically manage capture resolution and encoding parameters.
Simulcast resolutions and behavior
WebRTC ultimately controls how much data is being sent to the network based on its bandwidth estimation algorithm. It's very hard to circumvent the estimated bandwidth or trick WebRTC into sending more than it estimates. Most browsers expose WebRTC peer connection statistics which developers can access to retrieve the estimated available bandwidths for uplink or downlink.
The estimated available bandwidth reveals some information of the health of the E2E network and can trigger various WebRTC behaviors when facing network adversity or in recovering from a network glitch. SimulcastUplinkPolicy does its best to anticipate and react to the underlying WebRTC behavior and work with it to avoid further impact on the video quality of services.
The SimulcastUplinkPolicy implements the following logic:
The table entries represent the maximum configuration. When CPU and bandwidth consumption is overused, WebRTC will dynamically adjust bitrate, disable a layer or scale down resolution. The SimulcastUplinkPolicy has a monitoring mechanism which tracks the sending status and automatically adjusts without need for application intervention.
Downlink Bandwidth Policy
The VideoAdaptiveProbePolicy adds functionality to take advantage of video simulcast. The goal of this policy is to leave the complexity of managing the downlink bandwidth and decision of which streams to request inside the SDK and remove that burden from the application. The policy monitors numerous pieces of information and uses that to determine which streams to subscribe to. The data considered are:
The policy works by listening to any changes in the information listed above. Anytime there is a change it re-evaluates the best mix of remote videos to fit within the target downlink bandwidth. The policy is currently configured to try to request as many remote clients as possible, then increase resolution where possible. It prioritizes screen share video above people video. If there is insufficient bandwidth to request all far participants then only a certain number will be seen.
Applications will receive notifications of remote video being added or removed through the videoTileDidUpdate and videoTileWasRemoved callbacks. You can use encodingSimulcastLayersDidChange to know when the selected upstream simulcast resolutions change.
If the application pauses a remote video by calling pauseVideoTile, then this policy will not include that remote video in the list of available streams and therefore will not automatically subscribe or unsubscribe from it while it is in the paused state.
When using the policy it is recommended that applications do not take action on the downlink monitoring events such as videoNotReceivingEnoughData or estimatedDownlinkBandwidthLessThanRequired since it may conflict with decisions being made within the policy.
The VideoAdaptiveProbePolicy can be used with or without simulcast. To enable it without simulcast set the MeetingSessionConfiguration.videoDownlinkBandwidthPolicy to VideoAdaptiveProbePolicy. If simulcast is not active, then the policy will only be able to add or remove remote videos.
Creating a simulcast enabled meeting
First, create a meeting session configuration.
import { ConsoleLogger, DefaultDeviceController, DefaultMeetingSession, LogLevel, MeetingSessionConfiguration } from 'amazon-chime-sdk-js'; const logger = new ConsoleLogger('MyLogger', LogLevel.INFO); const deviceController = new DefaultDeviceController(logger); // You need responses from server-side Chime API. See 'Getting responses from your server application' in the README. const meetingResponse = // The response from the CreateMeeting API action. const attendeeResponse = // The response from the CreateAttendee or BatchCreateAttendee API action. // This meeting session configuration will be used to enable simulcast in the next step. const configuration = new MeetingSessionConfiguration(meetingResponse, attendeeResponse);
Now you have to enable
enableUnifiedPlanForChromiumBasedBrowsers
andenableSimulcastForUnifiedPlanChromiumBasedBrowsers
feature flags in the created MeetingSessionConfiguration.configuration.enableUnifiedPlanForChromiumBasedBrowsers = true; configuration.enableSimulcastForUnifiedPlanChromiumBasedBrowsers = true;
Now create a meeting session with the simulcast enabled meeting session configuration.
// In the examples below, you will use this meetingSession object. const meetingSession = new DefaultMeetingSession( configuration, logger, deviceController );
This
meetingSession
is now simulcast enabled and will have thevideoUplinkBandwidthPolicy
set to DefaultSimulcastUplinkPolicy andvideoDownlinkBandwidthPolicy
set to VideoAdaptiveProbePolicy. Due to these policies, the local and remote video resolutions may change. The video resolution depends on the available simulcast streams. The available simlucast streams are dependent on the number of attendees and the current bandwidth estimations. Check "Simulcast resolutions and behavior" section in this guide for more information.Receive upstream simulcast layer change notification
The active simulcast streams are represented by the SimulcastLayers enum. Currently, the active upstream simulcast layers will only be either "Low and High", or "Low and Medium" or "Low". To receive upstream simulcast layer change notification do the following steps:
Implement the encodingSimulcastLayersDidChange method from the AudioVideoObserver interface.
Then, add an instance of the
AudioVideoObserver
using the addObserver method so you can receive the changed simulcast layer notification.Now when you are in a simulcast enabled meeting and your upstream simulcast layer is changed, you will be notified in the
encodingSimulcastLayersDidChange
callback with the updated simulcast layer.import { SimulcastLayers } from 'amazon-chime-sdk-js'; const SimulcastLayersMapping = { [SimulcastLayers.Low]: 'Low', [SimulcastLayers.LowAndMedium]: 'Low and Medium', [SimulcastLayers.LowAndHigh]: 'Low and High', [SimulcastLayers.Medium]: 'Medium', [SimulcastLayers.MediumAndHigh]: 'Medium and High', [SimulcastLayers.High]: 'High' }; const observer = { encodingSimulcastLayersDidChange: simulcastLayers => { console.log(`current active simulcast layers changed to: ${SimulcastLayersMapping[simulcastLayers]}`); } } meetingSession.audioVideo.addObserver(observer);
Give feedback on this guide


April, 2016
Functional Programming
For my first post I want to start a collection of resources I have come across that help to describe and explain functional programming. Last summer I accepted an internship position at Mentor Graphics, and my team lead, Joe Barnes, suggested a MOOC (Massive Open Online Course) to help prepare me and get my feet wet with Scala and the functional programming paradigm in general. He recommended I start with Functional Programming Principles in Scala, a course instructed by Martin Odersky, designer of the Scala language, on Coursera. This course was my first exposure to functional programming in any way.
In the last nine or so months, I feel like I have been exposed to and experienced "a whole new world." I have fallen in love with FP (functional programming). But along the way I've really had to learn what exactly is functional programming. Not only for my own understanding, but I've had conversations with my classmates, with typically the same experience as I had before, and needed to be able to properly explain my new found discovery of awesomeness. Discussion also began in the monthly functional meet-up group, HuntFunc, on how to have meaningful conversations with others new to the functional programming paradigm.
I will come back to more language specific resources in a moment. Each language has its pros and cons, but we need to understand the defining characteristics of this usually unfamiliar paradigm before we try to compare the various tools that try to execute it. Kris Jenkins wrote two great posts in December on the topic. Part 1: What is Functional Programming? and Part 2: Which Programming Languages are Functional?. These two are my new favorite posts and emphasise how in the FP world complexity and side-effects are evil and the importance of avoiding them and striving for more pure functions.
Programming languages can be typically viewed on a scale of how functional it is. Scala is considered a hybrid language, that allows for object-oriented and functional paradigms, and is often looked at as a bridge from OO (Java, in particular) to FP. From the Scala world, the courses that I mentioned earlier (and a few more) are being transitioned to the new ScalaCenter, which will soon offer a Scala mini-degree offered on Coursera. On the paradigm scale, Haskell is located closer to the functional side. Although I have yet to finish this ebook, Christopher Allen and Julie Moronuki have introduced Haskell Programming from First Principles, and it is looking very promising so far.
I think this will be enough of my rambling for my first blog post. I think I may delve further into the various programming languages that are closer to the functional programming side of the paradigm scale next time and discuss various differences they have, such as static or dynamic typing. Thanks for reading!


You need a website and you need it now! But you don't know where to get started with it and you don't have a five-figure budget. You're prepared to DIY, but you could use some help.
It's a Squarespace website with all of the parts that you don't know that you need. You work with your designer to figure out what you need where and how to DIY all the parts because you don't have $5,000 to spend on your first website.
 You're building a client base and now you're ready to turn strangers into clients with your website. You want to work with someone to figure what to put on your website, get it up and running in 30 days, and be able to manage it on your own.
Hi, i'm Aleia Walker a Freelance Web Designer/Developer and Web Development Instructor.
Three years ago I was an unhappy corporate drone. I did not feel valued at work and no one missed when I was gone.
I knew that something needed to change, so I started looking for skills that would make me more attractive - skills that would let me quit my full-time job and work on my own terms.
I tested out a few side hustles. Calligraphy, woodworking, business writing, and social media strategy to name a few untilsettling on web development and design - it's now one of my greatest passions!
It wasn't an easy journey and I did not have limitless funds or time - so I made sure I could learn and apply a lot in a little time, with little money.
Six months after starting to learn new skills, I started freelancing. And a year later, I quit my full-time job. And I feel like I provide value to someone every damn day.
Are you next?


This is a reference guide for developers who are consuming Webhook Events and need to understand the structure of the events being sent. Transmitting events to a server for your web or mobile application provides near real-time detailed information about your Email Transmissions.
There are several types of events which provide data to your system concerning an email's life cycle. They are organized by Event Types which contain various Events with each Event being composed of Event Properties. The following tables can be used as a reference while working with Webhooks
See also:
Webhooks: Beyond The Basics
Webhook are JSON objects. A single POST constains an array of events. Here is an exampe of actual Webhook data:
[
{
"msys": {
"message_event": {
"timestamp": "1479333170",
"friendly_from"<EMAIL_ADDRESS>"msg_size": "3006",
"customer_id": "1521",
"subject": "Sending with SparkPost is Fun",
"template_version": "0",
"template_id": "template_30423932846795350",
"routing_domain": "example.com",
"rcpt_to"<EMAIL_ADDRESS>"event_id": "30423932847017907",
"sending_ip": "<IP_ADDRESS>",
"transmission_id": "30423932846795350",
"ip_pool": "shared",
"rcpt_meta": {},
"msg_from"<EMAIL_ADDRESS>"message_id": "000132d52c58b7630362",
"rcpt_tags": [],
"type": "injection",
"raw_rcpt_to"<EMAIL_ADDRESS>}
}
},
{
"msys": {
"message_event": {
"rcpt_to"<EMAIL_ADDRESS>"subject": "Sending with SparkPost is Fun",
"customer_id": "1521",
"transmission_id": "30423932846795350",
"event_id": "30423932847017911",
"timestamp": "1479333170",
"friendly_from"<EMAIL_ADDRESS>"routing_domain": "example.com",
"template_version": "0",
"ip_pool": "shared",
"type": "injection",
"rcpt_meta": {},
"template_id": "template_30423932846795350",
"msg_from"<EMAIL_ADDRESS>"rcpt_tags": [],
"message_id": "000132d52c58b7630462",
"sending_ip": "<IP_ADDRESS>",
"msg_size": "3101",
"raw_rcpt_to"<EMAIL_ADDRESS>}
}
}
]
The rest of this document defines the various webhook events and the fields the events contain.


Password Verification
Username:
Password:
Register
Password must meet the following requirements:
At least
one letter
At least
one capital letter
At least
one number
Be at least
8 characters


I've always been a tech-obsessed tinkerer. My passion for experimenting with technology has equipped me with a wide variety of technical skills. I employ many of them when building a website: designing visuals, programming in multiple languages, creating a smooth user experience, and more. I enjoy the challenge of each project and take pride in the knowledge that the outcome has been so useful for my clients. By providing individuals and businesses with a web presence, I enable them to engage with a wider audience.
Years ago, I started a small business offering computer help to my neighbors. I would remove viruses/adware/spyware and troubleshoot problems with both hardware and software. I always offered to optimize startup speed and responsiveness by auditing the various hidden processes and services that cause hang-ups. Though the range of my services has grown, my basic commitment has remained the same. I do my best to leave customers with a system that’s a joy to use.
I designed and built this responsive website with Bootstrap. As directed by the client, I focused on simplicity and ease of use for the pharmacy's elderly customers. The single-page design is mobile-first and supports all display sizes. A clear call-to-action greets visitors and guides them to directions and contact information for the pharmacy's eight locations.
I compressed images, wrote custom CSS rather than bring in heavy frameworks, and used the minified version of Bootstrap delivered over a CDN. These optimizations bring the entire website under 2MB for a snappy load time even on slow or unreliable mobile data connections.
Close ProjectA dynamic, engaging introduction to M Patricia Diaz and her recently completed memoir manuscript: Forgive Me. The bold and bright color scheme is inspired by the author’s hometown of Maracaibo, Venezuela. This website is built on WordPress, which allows M Patricia to publish blog posts keeping her readers informed on the book’s progress.
Close ProjectA primer on principles of Effective Altruism where visitors are encouraged to join their local EA group. They may also contact the organizers and browse various links related to the movement. The fully responsive layout enables easy reading on all devices.
Close ProjectLorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia neque assumenda ipsam nihil, molestias magnam, recusandae quos quis inventore quisquam velit asperiores, vitae? Reprehenderit soluta, eos quod consequuntur itaque. Nam.
Close ProjectLorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia neque assumenda ipsam nihil, molestias magnam, recusandae quos quis inventore quisquam velit asperiores, vitae? Reprehenderit soluta, eos quod consequuntur itaque. Nam.
Close ProjectLorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia neque assumenda ipsam nihil, molestias magnam, recusandae quos quis inventore quisquam velit asperiores, vitae? Reprehenderit soluta, eos quod consequuntur itaque. Nam.
Close Project


AKB48's General Manager shows her support for IZ*ONE
by honeyciderDuring the November 19 broadcast of 'Saku no Ki' on "bayfm", which Sakura Miyawaki regularly hosts, AKB48's general manager, Mukaichi Mion, filled in as the hoston Sakura's behalf. Bayfm stated that Sakura was unable to participate in this broadcast due to other IZ*ONE activities.
During the broadcast, Mion read supportive letters from fans all over the world for the members of IZ*ONE.
After the broadcast, Mion posted a tweet stating "Thank you to everyone who listened to yesterday's broadcast. May everyone's feelings reach the 12 members." Then ended the tweet with the hashtags #Saku no Ki #WeTogetherWithIZONE.
You can see her tweet below:


Two player game(Using Two Dice).Each player has 5 life.
Each player has to achieve the respective sum as Player 1 have to achieve the Even Sum and Player 2 have to achieve the Odd Sum by rolling two dice simultaneously,
After rolling the dice the sum of numbers on the dice will be recorded.
If he/she will get the sum, he/she will get +5 points each or else he/she will get -2 points..
Player has only one chance to roll the dice at a time.
If the player fail to roll the dice within 10sec, then he/she will loose one life-line & score updated with -2 points.
The player who loses all life-line’s first he/she will be looser & other player will win the game. Score is not considered in this case.
The player who reach the target point first, will be the winner.


Querying...
These past few days I've been working on a project for DevBootCamp which required me to search for similar Objects by columns. After banging my head for awhile, trying to use one-to-one relationships and polymorphic pathing, my friend Gunnari gave me a lightbulb. Why not use query strings? And so here is the view and corresponding controller for query strings in Rails 4.
In the view, we set the key as :query and in the controller I use a case statement for the key on line 3.